From e007b3226160e1ce0bfe4984550d99db63866987 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 7 Jan 2016 15:34:16 +0000 Subject: [PATCH 01/18] Functions to clear all data relating to individual services Addresses #272 --- services/tasks.py | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 services/tasks.py diff --git a/services/tasks.py b/services/tasks.py new file mode 100644 index 00000000..60a30bd3 --- /dev/null +++ b/services/tasks.py @@ -0,0 +1,114 @@ +from authentication.models import AuthServicesInfo +from celerytask.models import SyncGroupCache +from django.conf import settings +import logging +from services.models import UserTSgroup +from services.models import AuthTS +from services.models import TSgroup +from services.models import DiscordAuthToken + +logger = logging.getLogger(__name__) + +def disable_teamspeak(): + if settings.ENABLE_AUTH_TEAMSPEAK3: + logger.warn("ENABLE_AUTH_TEAMSPEAK3 still True, after disabling users will still be able to create teamspeak accounts") + if settings.ENABLE_BLUE_TEAMSPEAK3: + logger.warn("ENABLE_BLUE_TEAMSPEAK3 still True, after disabling blues will still be able to create teamspeak accounts") + for auth in AuthServicesInfo.objects.all(): + if auth.teamspeak3_uid: + logger.info("Clearing %s Teamspeak3 UID" % auth.user) + auth.teamspeak3_uid = '' + auth.save() + if auth.teamspeak3_perm_key: + logger.info("Clearing %s Teamspeak3 permission key" % auth.user) + auth.teamspeak3_perm_key = '' + auth.save() + logger.info("Deleting all UserTSgroup models") + UserTSgroup.objects.all().delete() + logger.info("Deleting all AuthTS models") + AuthTS.objects.all().delete() + logger.info("Deleting all TSgroup models") + TSgroup.objects.all().delete() + logger.info("Teamspeak3 disabled") + +def disable_forum(): + if settings.ENABLE_AUTH_FORUM: + logger.warn("ENABLE_AUTH_FORUM still True, after disabling users will still be able to create forum accounts") + if settings.ENABLE_BLUE_FORUM: + logger.warn("ENABLE_BLUE_FORUM still True, after disabling blues will still be able to create forum accounts") + for auth in AuthServicesInfo.objects.all(): + if auth.forum_username: + logger.info("Clearing %s forum username" % auth.user) + auth.forum_username = '' + auth.save() + if auth.forum_password: + logger.info("Clearing %s forum password" % auth.user) + auth.forum_password = '' + auth.save() + logger.info("Deleting all SyncGroupCache models for forum") + SyncGroupCache.objects.filter(servicename="forum").delete() + +def disable_jabber(): + if settings.ENABLE_AUTH_JABBER: + logger.warn("ENABLE_AUTH_JABBER still True, after disabling users will still be able to create jabber accounts") + if settings.ENABLE_BLUE_JABBER: + logger.warn("ENABLE_BLUE_JABBER still True, after disabling blues will still be able to create jabber accounts") + for auth in AuthServicesInfo.objects.all(): + if auth.jabber_username: + logger.info("Clearing %s jabber username" % auth.user) + auth.jabber_username = '' + auth.save() + if auth.jabber_password: + logger.info("Clearing %s jabber password" % auth.user) + auth.jabber_password = '' + auth.save() + logger.info("Deleting all SyncGroupCache models for jabber") + SyncGroupCache.objects.filter(servicename="jabber").delete() + +def disable_mumble(): + if settings.ENABLE_AUTH_MUMBLE: + logger.warn("ENABLE_AUTH_MUMBLE still True, after disabling users will still be able to create mumble accounts") + if settings.ENABLE_BLUE_MUMBLE: + logger.warn("ENABLE_BLUE_MUMBLE still True, after disabling blues will still be able to create mumble accounts") + for auth in AuthServicesInfo.objects.all(): + if auth.mumble_username: + logger.info("Clearing %s mumble username" % auth.user) + auth.mumble_username = '' + auth.save() + if auth.mumble_password: + logger.info("Clearing %s mumble password" % auth.user) + auth.mumble_password = '' + auth.save() + logger.info("Deleting all SyncGroupCache models for mumble") + SyncGroupCache.objects.filter(servicename="mumble").delete() + +def disable_ipboard(): + if settings.ENABLE_AUTH_IPBOARD: + logger.warn("ENABLE_AUTH_IPBOARD still True, after disabling users will still be able to create IPBoard accounts") + if settings.ENABLE_BLUE_IPBOARD: + logger.warn("ENABLE_BLUE_IPBOARD still True, after disabling blues will still be able to create IPBoard accounts") + for auth in AuthServicesInfo.objects.all(): + if auth.ipboard_username: + logger.info("Clearing %s ipboard username" % auth.user) + auth.ipboard_username = '' + auth.save() + if auth.ipboard_password: + logger.info("Clearing %s ipboard password" % auth.user) + auth.ipboard_password = '' + auth.save() + logger.info("Deleting all SyncGroupCache models for ipboard") + SyncGroupCache.objects.filter(servicename="ipboard").delete() + + +def disable_discord(): + if settings.ENABLE_AUTH_DISCORD: + logger.warn("ENABLE_AUTH_DISCORD still True, after disabling users will still be able to link Discord accounts") + if settings.ENABLE_BLUE_DISCORD: + logger.warn("ENABLE_BLUE_DISCORD still True, after disabling blues will still be able to link Discord accounts") + for auth in AuthServicesInfo.objects.all(): + if auth.discord_uid: + logger.info("Clearing %s Discord UID" % auth.user) + auth.discord_uid = '' + auth.save() + logger.info("Deleting all DiscordAuthToken models") + DiscordAuthToken.objects.all().delete() From a3378760352b9cb8b6c4e7119175db46032112bc Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 20:55:53 +0000 Subject: [PATCH 02/18] Parallelize corp and alliance model updates - if corp joins alliance which is blue, it may take 2 cycles for blue status to be reflected due to async updates Addresses #103 --- celerytask/tasks.py | 61 ++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 571c5b77..5015798c 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -2,7 +2,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 celery import task from models import SyncGroupCache from celery.task.schedules import crontab from services.managers.openfire_manager import OpenfireManager @@ -522,6 +522,39 @@ def populate_alliance(id, blue=False): EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'], corpinfo['members']['current'], blue, alliance) +@task +def update_alliance(id): + alliance = EveAllianceInfo.objects.get(alliance_id=id) + corps = EveCorporationInfo.objects.filter(alliance=alliance) + logger.debug("Updating alliance %s with %s member corps" % (alliance, len(corps))) + allianceinfo = EveApiManager.get_alliance_information(alliance.alliance_id) + if allianceinfo: + EveManager.update_alliance_info(allianceinfo['id'], allianceinfo['executor_id'], + allianceinfo['member_count'], alliance.is_blue) + for corp in corps: + if corp.corporation_id in allianceinfo['member_corps'] is False: + logger.info("Corp %s no longer in alliance %s" % (corp, alliance)) + corp.alliance = None + corp.save() + populate_alliance(alliance.alliance_id, blue=alliance.is_blue) + elif EveApiManager.check_if_alliance_exists(alliance.alliance_id) is False: + logger.info("Alliance %s has closed. Deleting model" % alliance) + alliance.delete() + +@task +def update_corp(id): + corp = EveCorporationInfo.objects.get(corporation_id=id) + logger.debug("Updating corp %s" % corp) + corpinfo = EveApiManager.get_corporation_information(corp.corporation_id) + if corpinfo: + alliance = None + if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists(): + alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id']) + EveManager.update_corporation_info(corpinfo['id'], corpinfo['members']['current'], alliance, corp.is_blue) + elif EveApiManager.check_if_corp_exists(corp.corporation_id) is False: + logger.info("Corp %s has closed. Deleting model" % corp) + corp.delete() + # Run Every 2 hours @periodic_task(run_every=crontab(minute=0, hour="*/2")) def run_corp_update(): @@ -595,33 +628,11 @@ def run_corp_update(): # update existing corp models for corp in EveCorporationInfo.objects.all(): - logger.debug("Updating corp %s" % corp) - corpinfo = EveApiManager.get_corporation_information(corp.corporation_id) - if corpinfo: - alliance = None - if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists(): - alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id']) - EveManager.update_corporation_info(corpinfo['id'], corpinfo['members']['current'], alliance, corp.is_blue) - elif EveApiManager.check_if_corp_exists(corp.corporation_id) is False: - logger.info("Corp %s has closed. Deleting model" % corp) - corp.delete() + update_corp.delay(corp.corporation_id) # update existing alliance models for alliance in EveAllianceInfo.objects.all(): - logger.debug("Updating alliance %s" % alliance) - allianceinfo = EveApiManager.get_alliance_information(alliance.alliance_id) - if allianceinfo: - EveManager.update_alliance_info(allianceinfo['id'], allianceinfo['executor_id'], - allianceinfo['member_count'], alliance.is_blue) - for corp in EveCorporationInfo.objects.filter(alliance=alliance): - if corp.corporation_id in allianceinfo['member_corps'] is False: - logger.info("Corp %s no longer in alliance %s" % (corp, alliance)) - corp.alliance = None - corp.save() - populate_alliance(alliance.alliance_id, blue=alliance.is_blue) - elif EveApiManager.check_if_alliance_exists(alliance.alliance_id) is False: - logger.info("Alliance %s has closed. Deleting model" % alliance) - alliance.delete() + update_alliance.delay(alliance.alliance_id) # create standings standings = EveApiManager.get_corp_standings() From ece06a683246b7a970976d0bac878d906c365e62 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 21:16:16 +0000 Subject: [PATCH 03/18] Toggle assignment of alliance groups --- alliance_auth/settings.py.example | 2 ++ celerytask/tasks.py | 31 +++++++++++++++++++++++++++++++ util/common_task.py | 2 ++ 3 files changed, 35 insertions(+) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 830ed9ad..08fd6cdd 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -221,7 +221,9 @@ FORUM_URL = os.environ.get('AA_FORUM_URL', '') DEFAULT_AUTH_GROUP = os.environ.get('AA_DEFAULT_ALLIANCE_GROUP', 'Member') DEFAULT_BLUE_GROUP = os.environ.get('AA_DEFAULT_BLUE_GROUP', 'Blue') MEMBER_CORP_GROUPS = 'True' == os.environ.get('AA_MEMBER_CORP_GROUPS', 'True') +MEMBER_ALLIANCE_GROUPS = 'True' == os.environ.get('AA_MEMBER_ALLIANCE_GROUPS', 'False') BLUE_CORP_GROUPS = 'True' == os.environ.get('AA_BLUE_CORP_GROUPS', 'False') +BLUE_ALLIANCE_GROUPS = 'True' == os.environ.get('AA_BLUE_ALLIANCE_GROUPS', 'False') ######################### # Alliance Service Setup diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 571c5b77..0d351cfb 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -23,6 +23,7 @@ from util import check_if_user_has_permission from util.common_task import add_user_to_group from util.common_task import remove_user_from_group from util.common_task import generate_corp_group_name +from util.common_task import generate_alliance_group_name from eveonline.models import EveCharacter from eveonline.models import EveCorporationInfo from eveonline.models import EveAllianceInfo @@ -271,6 +272,34 @@ def assign_corp_group(auth): logger.info("Removing user %s from old corpgroup %s" % (auth.user, g)) auth.user.groups.remove(g) +def assign_alliance_group(auth): + alliance_group = None + 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) + if char.alliance_name: + alliancename = generate_corp_group_name(char.alliance_name) + state = determine_membership_by_character(char) + if state == "BLUE" and settings.BLUE_ALLIANCE_GROUPS: + logger.debug("Validating blue user %s has alliance group assigned." % auth.user) + alliance_group, c = Group.objects.get_or_create(name=alliancename) + elif state == "MEMBER" and settings.MEMBER_ALLIANCE_GROUPS: + logger.debug("Validating member %s has alliance group assigned." % auth.user) + alliance_group, c = Group.objects.get_or_create(name=alliancename) + else: + logger.debug("Ensuring non-member %s has no alliance groups assigned." % auth.user) + else: + logger.debug("User %s main character %s not in an alliance. Ensuring no allinace group assigned." % (auth.user, char)) + if alliance_group: + if not alliance_group in auth.user.groups.all(): + logger.info("Adding user %s to alliance group %s" % (auth.user, alliance_group)) + auth.user.groups.add(alliance_group) + for g in auth.user.groups.all(): + if str.startswith(str(g.name), "Alliance_"): + if g != alliance_group: + logger.info("Removing user %s from old alliancegroup %s" % (auth.user, g)) + auth.user.groups.remove(g) + def make_member(user): logger.debug("Ensuring user %s has member permissions and groups." % user) # ensure member is not blue right now @@ -295,6 +324,7 @@ def make_member(user): auth.is_blue = False auth.save() assign_corp_group(auth) + assign_alliance_group(auth) def make_blue(user): logger.debug("Ensuring user %s has blue permissions and groups." % user) @@ -320,6 +350,7 @@ def make_blue(user): auth.is_blue = True auth.save() assign_corp_group(auth) + assign_alliance_group(auth) def determine_membership_by_character(char): if settings.IS_CORP: diff --git a/util/common_task.py b/util/common_task.py index c29f5aee..c4b9d88f 100755 --- a/util/common_task.py +++ b/util/common_task.py @@ -70,3 +70,5 @@ def deactivate_services(user): def generate_corp_group_name(corpname): return 'Corp_' + corpname.replace(' ', '_') +def generate_alliance_group_name(alliancename): + reutrn 'Alliance_' + alliancename.replace(' ', '_') From 7259e40267b47425f10b9bde3bb993bc1172a8b0 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 21:26:34 +0000 Subject: [PATCH 04/18] Corrected group name generation as alliance --- celerytask/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 0d351cfb..3226f024 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -278,7 +278,7 @@ def assign_alliance_group(auth): if EveCharacter.objects.filter(character_id=auth.main_char_id).exists(): char = EveCharacter.objects.get(character_id=auth.main_char_id) if char.alliance_name: - alliancename = generate_corp_group_name(char.alliance_name) + alliancename = generate_alliance_group_name(char.alliance_name) state = determine_membership_by_character(char) if state == "BLUE" and settings.BLUE_ALLIANCE_GROUPS: logger.debug("Validating blue user %s has alliance group assigned." % auth.user) From 1d3d1b53a48d7a48a0b8291918319227e3b8943c Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 22:07:08 +0000 Subject: [PATCH 05/18] Notify function --- notifications/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/notifications/__init__.py b/notifications/__init__.py index e69de29b..d12a961d 100644 --- a/notifications/__init__.py +++ b/notifications/__init__.py @@ -0,0 +1,12 @@ +from .models import Notification + +def notify(user, title, message=None, level='info'): + notif = Notification() + notif.user = user + notif.title = title + if not message: + message = Title + notif.message = message + notif.level = level + notif.save() + logger.info("Created notification %s" % notif From bfef9c3123755e2502ba75a01f3c6222f773e652 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 17:08:22 -0500 Subject: [PATCH 06/18] Lowered loglevel for evelink.APIError Prevents unnecessary notifications when getting info for a corp with a bad corp ID --- services/managers/eve_api_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/managers/eve_api_manager.py b/services/managers/eve_api_manager.py index ac79fefe..721ce02c 100644 --- a/services/managers/eve_api_manager.py +++ b/services/managers/eve_api_manager.py @@ -170,7 +170,7 @@ class EveApiManager(): logger.debug("Confirmed id %s is a corp." % corp_id) return True except evelink.api.APIError as error: - logger.exception("APIError occured while checking if id %s is corp. Possibly not corp?" % corp_id) + logger.debug("APIError occured while checking if id %s is corp. Possibly not corp?" % corp_id) logger.debug("Unable to verify id %s is corp." % corp_id) return False From 0807bc98a385886291230e90372ed91c6f52b928 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 22:30:43 +0000 Subject: [PATCH 07/18] Shorthand notify command Notifications on API key update failures Notifications on application status updates Notifications on services disabled --- celerytask/tasks.py | 37 +++++++++++++++++++++++++++++++++---- hrapplications/views.py | 6 +++++- notifications/__init__.py | 4 ++-- util/common_task.py | 12 ++++++++++-- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 571c5b77..6fc62ffa 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -2,7 +2,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 notifications import notify from models import SyncGroupCache from celery.task.schedules import crontab from services.managers.openfire_manager import OpenfireManager @@ -34,14 +34,18 @@ import logging logger = logging.getLogger(__name__) def disable_member(user): + change = False 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() + change = True if user.groups.all().exists(): logger.info("Clearing user %s groups to deactivate user." % user) user.groups.clear() + change = True deactivate_services(user) + return change def is_teamspeak3_active(): return settings.ENABLE_AUTH_TEAMSPEAK3 or settings.ENABLE_BLUE_TEAMSPEAK3 @@ -272,54 +276,68 @@ def assign_corp_group(auth): auth.user.groups.remove(g) def make_member(user): + change = False 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') + change = True 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) + change = True # 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') + change = True member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP) if not member_group in user.groups.all(): logger.info("Adding user %s to member group" % user) user.groups.add(member_group) + change = True 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() + change = True assign_corp_group(auth) + return change def make_blue(user): + change = False 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') + change = True 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) + change = True # 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') + change = True blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP) if not blue_group in user.groups.all(): logger.info("Adding user %s to blue group" % user) user.groups.add(blue_group) + change = True 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() + change = True assign_corp_group(auth) + return change def determine_membership_by_character(char): if settings.IS_CORP: @@ -357,14 +375,17 @@ def determine_membership_by_user(user): return False def set_state(user): + change = False state = determine_membership_by_user(user) logger.debug("Assigning user %s to state %s" % (user, state)) if state == "MEMBER": - make_member(user) + change = make_member(user) elif state == "BLUE": - make_blue(user) + change = make_blue(user) else: - disable_member(user) + change = disable_member(user) + if change: + notify(user, "Membership State Change", message="You membership state has been changed to %s" % state) # Run every minute @periodic_task(run_every=crontab(minute="*/1")) @@ -414,6 +435,7 @@ def refresh_api(api_key_pair): 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 + notify(user, "API Failed Validation", message="Your API key ID %s is not account-wide as required." % api_key_pair.api_id, level="danger") 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 @@ -423,6 +445,7 @@ def refresh_api(api_key_pair): 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 + notify(user, "API Failed Validation", message="Your API key ID %s does not meet access mask requirements." % api_key_pair.api_id, level="danger") 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) @@ -434,6 +457,7 @@ def refresh_api(api_key_pair): 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 + notify(user, "API Failed Validation", message="Your API key ID %s is not account-wide as required." % api_key_pair.api_id, level="danger") 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 @@ -443,14 +467,17 @@ def refresh_api(api_key_pair): 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 + notify(user, "API Failed Validation", message="Your API key ID %s does not meet access mask requirements." % api_key_pair.api_id, level="danger") 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 + notify(user, "API Failed Validation", message="Your API key ID %s has accumulated too many errors during refresh and is assumed to be invalid." % api_key_pair.api_id, level="danger") 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) + notify(user, "API Key Deleted", message="Your API key ID %s has failed validation. It and its associated characters have been deleted." % api_key_pair.api_id, level="danger") 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) @@ -473,6 +500,7 @@ def refresh_api(api_key_pair): 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) + notify(user, "API Key Deleted", message="Your API key ID %s is invalid. It and its associated characters have been deleted." % api_key_pair.api_id, level="danger") # Run every 3 hours @periodic_task(run_every=crontab(minute=0, hour="*/3")) @@ -495,6 +523,7 @@ def run_api_refresh(): logger.info("User %s main character id %s missing model. Clearning main character." % (user, authserviceinfo.main_char_id)) authserviceinfo.main_char_id = '' authserviceinfo.save() + notify(user, "Main Character Reset", message="Your specified main character no longer has a model.\nThis could be the result of an invalid API\nYour main character ID has been reset." % api_key_pair.api_id, level="warn") set_state(user) def populate_alliance(id, blue=False): diff --git a/hrapplications/views.py b/hrapplications/views.py index 903121c9..998be473 100755 --- a/hrapplications/views.py +++ b/hrapplications/views.py @@ -3,7 +3,7 @@ from django.shortcuts import render_to_response from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import login_required from django.shortcuts import HttpResponseRedirect - +from notifications import notify from models import HRApplication from models import HRApplicationComment from forms import HRApplicationForm @@ -162,6 +162,7 @@ def hr_application_remove(request, app_id): application = HRApplication.objects.get(id=app_id) if application: logger.info("Deleted HRApplication id %s on behalf of user %s" % (app_id, request.user)) + notify(application.user, "Application Deleted", message="Your application to %s was deleted.") application.delete() else: logger.error("Unable to delete HRApplication with id %s on behalf of user %s: application is NoneType" % (app_id, request.user)) @@ -183,6 +184,7 @@ def hr_application_approve(request, app_id): application.reviewer_character = EveCharacter.objects.get(character_id=auth_info.main_char_id) application.save() logger.info("HRApplication for user %s to corp %s approved by %s" % (application.user, application.corp, request.user)) + notify(application.user, "Application Accepted", message="Your application to %s has been approved." % application.corp, level="success") else: logger.error("User %s unable to approve HRApplication id %s - hrapplication with that id not found." % (request.user, app_id)) @@ -201,6 +203,7 @@ def hr_application_reject(request, app_id): application.reviewer_character = EveCharacter.objects.get(character_id=auth_info.main_char_id) application.save() logger.info("HRApplication for user %s to corp %s rejected by %s" % (application.user, application.corp, request.user)) + notify(application.user, "Application Rejected", message="Your application to %s has been rejected." % application.corp, level="danger") else: logger.error("User %s unable to reject HRApplication id %s - hrapplication with that id not found." % (request.user, app_id)) @@ -251,6 +254,7 @@ def hr_application_mark_in_progress(request, app_id): application.reviewer_inprogress_character = EveCharacter.objects.get(character_id=auth_info.main_char_id) application.save() logger.info("Marked HRApplication for user %s to corp %s in progress by user %s" % (application.user, application.corp, request.user)) + notify(application.user, "Application In Progress", message="Your application to %s is being reviewed by %s" % (application.corp, application.reviewer_inprogress_character)) else: logger.error("Unable to mark HRApplication id %s in progress by user %s - hrapplication matching id not found." % (app_id, request.user)) diff --git a/notifications/__init__.py b/notifications/__init__.py index d12a961d..3e095793 100644 --- a/notifications/__init__.py +++ b/notifications/__init__.py @@ -5,8 +5,8 @@ def notify(user, title, message=None, level='info'): notif.user = user notif.title = title if not message: - message = Title + message = title notif.message = message notif.level = level notif.save() - logger.info("Created notification %s" % notif + logger.info("Created notification %s" % notif) diff --git a/util/common_task.py b/util/common_task.py index c29f5aee..0c98406f 100755 --- a/util/common_task.py +++ b/util/common_task.py @@ -1,6 +1,6 @@ from django.contrib.auth.models import Group from django.contrib.auth.models import User - +from notifications import notify from authentication.managers import AuthServicesInfoManager from services.managers.openfire_manager import OpenfireManager from services.managers.phpbb3_manager import Phpbb3Manager @@ -39,33 +39,41 @@ def remove_user_from_group(user, groupname): def deactivate_services(user): + change = False logger.debug("Deactivating services for user %s" % user) authinfo = AuthServicesInfoManager.get_auth_service_info(user) if authinfo.mumble_username and authinfo.mumble_username != "": logger.debug("User %s has mumble account %s. Deleting." % (user, authinfo.mumble_username)) MumbleManager.delete_user(authinfo.mumble_username) AuthServicesInfoManager.update_user_mumble_info("", "", user) + change = True if authinfo.jabber_username and authinfo.jabber_username != "": logger.debug("User %s has jabber account %s. Deleting." % (user, authinfo.jabber_username)) OpenfireManager.delete_user(authinfo.jabber_username) AuthServicesInfoManager.update_user_jabber_info("", "", user) + change = True if authinfo.forum_username and authinfo.forum_username != "": logger.debug("User %s has forum account %s. Deleting." % (user, authinfo.forum_username)) Phpbb3Manager.disable_user(authinfo.forum_username) AuthServicesInfoManager.update_user_forum_info("", "", user) + change = True if authinfo.ipboard_username and authinfo.ipboard_username != "": logger.debug("User %s has ipboard account %s. Deleting." % (user, authinfo.ipboard_username)) IPBoardManager.disable_user(authinfo.ipboard_username) AuthServicesInfoManager.update_user_forum_info("", "", user) + change = True if authinfo.teamspeak3_uid and authinfo.teamspeak3_uid != "": logger.debug("User %s has mumble account %s. Deleting." % (user, authinfo.teamspeak3_uid)) Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) AuthServicesInfoManager.update_user_teamspeak3_info("", "", user) + change = True if authinfo.discord_uid and authinfo.discord_uid != "": logger.debug("User %s has discord account %s. Deleting." % (user, authinfo.discord_uid)) DiscordManager.delete_user(authinfo.discord_uid) AuthServicesInfoManager.update_user_discord_info("", user) - + change = True + if change: + notify(user, "Services Disabled", message="Your services accounts have been disabled.", level="danger") def generate_corp_group_name(corpname): return 'Corp_' + corpname.replace(' ', '_') From 86e9ea763477b6e7da764f1de7b560fe8aa79d58 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 17:35:08 -0500 Subject: [PATCH 08/18] typo --- util/common_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/common_task.py b/util/common_task.py index c4b9d88f..a22dbfb5 100755 --- a/util/common_task.py +++ b/util/common_task.py @@ -71,4 +71,4 @@ def generate_corp_group_name(corpname): return 'Corp_' + corpname.replace(' ', '_') def generate_alliance_group_name(alliancename): - reutrn 'Alliance_' + alliancename.replace(' ', '_') + return 'Alliance_' + alliancename.replace(' ', '_') From 54f01260589dd978f3026796303ad79aac21605f Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 17 Feb 2016 22:44:06 +0000 Subject: [PATCH 09/18] Removed conflict --- celerytask/tasks.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 99c2a21a..dd6281ef 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -2,11 +2,8 @@ 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 -<<<<<<< HEAD from notifications import notify -======= from celery import task ->>>>>>> 450f577860abad4644e02eb5a14a58bf047f17b2 from models import SyncGroupCache from celery.task.schedules import crontab from services.managers.openfire_manager import OpenfireManager From 715352faac5f9a98d68c7ae4168f67d46db8ad0e Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 18 Feb 2016 19:15:30 +0000 Subject: [PATCH 10/18] Notifications for group request status changes --- groupmanagement/views.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/groupmanagement/views.py b/groupmanagement/views.py index 8801a387..47ae1f22 100755 --- a/groupmanagement/views.py +++ b/groupmanagement/views.py @@ -5,7 +5,7 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required from django.contrib.auth.models import Group - +from notifications import notify from models import GroupDescription from models import GroupRequest from models import HiddenGroup @@ -48,6 +48,7 @@ def group_accept_request(request, group_request_id): group_request.user.save() group_request.delete() logger.info("User %s accepted group request from user %s to group %s" % (request.user, group_request.user, group_request.group.name)) + notify(group_request.user, "Group Application Accepted", level="success", message="Your application to %s has been accepted." % group_request.group) except: logger.exception("Unhandled exception occured while user %s attempting to accept grouprequest id %s." % (request.user, group_request_id)) pass @@ -65,6 +66,7 @@ def group_reject_request(request, group_request_id): if group_request: logger.info("User %s rejected group request from user %s to group %s" % (request.user, group_request.user, group_request.group.name)) group_request.delete() + notify(group_request.user, "Group Application Rejected", level="danger", message="Your application to %s has been rejected." % group_request.group) except: logger.exception("Unhandled exception occured while user %s attempting to reject group request id %s" % (request.user, group_request_id)) pass @@ -83,6 +85,7 @@ def group_leave_accept_request(request, group_request_id): group_request.user.save() group_request.delete() logger.info("User %s accepted group leave request from user %s to group %s" % (request.user, group_request.user, group_request.group.name)) + notify(group_request.user, "Group Leave Request Accepted", level="success", message="Your request to leave %s has been accepted." % group_request.group) except: logger.exception("Unhandled exception occured while user %s attempting to accept group leave request id %s" % (request.user, group_request_id)) pass @@ -100,6 +103,7 @@ def group_leave_reject_request(request, group_request_id): if group_request: group_request.delete() logger.info("User %s rejected group leave request from user %s for group %s" % (request.user, group_request.user, group_request.group.name)) + notify(group_request.user, "Group Leave Request Rejected", level="danger", message="Your request to leave %s has been rejected." % group_request.group) except: logger.exception("Unhandled exception occured while user %s attempting to reject group leave request id %s" % (request.user, group_request_id)) pass @@ -160,7 +164,6 @@ def group_request_add(request, group_id): grouprequest.leave_request = False grouprequest.save() logger.info("Created group request for user %s to group %s" % (request.user, Group.objects.get(id=group_id))) - return HttpResponseRedirect("/groups") From 8697d075a859543bb02ec95546ff763608f5b219 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 18 Feb 2016 19:24:03 +0000 Subject: [PATCH 11/18] Import logging to notify function --- notifications/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/notifications/__init__.py b/notifications/__init__.py index 3e095793..dedd2956 100644 --- a/notifications/__init__.py +++ b/notifications/__init__.py @@ -1,4 +1,7 @@ from .models import Notification +import logging + +logger = logging.getLogger(__name__) def notify(user, title, message=None, level='info'): notif = Notification() From 3d82dd84c9924fb708048a278a32650d5f715762 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 18 Feb 2016 19:42:00 +0000 Subject: [PATCH 12/18] Display newline characters in notification view --- notifications/handlers.py | 7 ++++++- stock/templates/registered/notification_view.html | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/notifications/handlers.py b/notifications/handlers.py index bdffeb33..9d11ad69 100644 --- a/notifications/handlers.py +++ b/notifications/handlers.py @@ -2,6 +2,8 @@ import logging from django.contrib.auth.models import User from .models import Notification +logger = logging.getLogger(__name__) + class NotificationHandler(logging.Handler): def emit(self, record): for user in User.objects.all(): @@ -10,5 +12,8 @@ class NotificationHandler(logging.Handler): notif.user = user notif.title = "%s [%s:%s]" % (record.levelname, record.funcName, record.lineno) notif.level = str([item[0] for item in Notification.LEVEL_CHOICES if item[1] == record.levelname][0]) - notif.message = record.getMessage() + message = record.getMessage() + message = message + "\n\n" + message = message + record.exc_text + notif.message = message notif.save() diff --git a/stock/templates/registered/notification_view.html b/stock/templates/registered/notification_view.html index 88bfb713..3c27e54b 100644 --- a/stock/templates/registered/notification_view.html +++ b/stock/templates/registered/notification_view.html @@ -13,7 +13,7 @@
{{ notif.timestamp }} {{ notif.title }}
-
{{ notif.message }}
+
{{ notif.message }}
From 6bbea6eedadcc0814235ec30a93a3a3e5993995e Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 18 Feb 2016 20:25:43 +0000 Subject: [PATCH 13/18] Added check to ensure api is valid before pulling characters --- eveonline/forms.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eveonline/forms.py b/eveonline/forms.py index 01c51849..eeba2f9e 100644 --- a/eveonline/forms.py +++ b/eveonline/forms.py @@ -24,7 +24,8 @@ class UpdateKeyForm(forms.Form): 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 EveApiManager.api_key_is_valid(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: + raise forms.ValidationError(u'API key is invalid') chars = EveApiManager.get_characters_from_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']).result states = [] states.append(self.user_state) From 4b3ee9c433fb353488bacb5c3cbf8e10e8b4a4d6 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 18 Feb 2016 20:32:30 +0000 Subject: [PATCH 14/18] Run initial boostrapping when updating --- update.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/update.sh b/update.sh index 443b4231..f8695c08 100644 --- a/update.sh +++ b/update.sh @@ -2,3 +2,4 @@ pip install --upgrade -r requirements.txt yes yes | python manage.py syncdb yes yes | python manage.py evolve --hint --execute yes yes | python manage.py collectstatic +python manage.py shell < run_alliance_corp_update.py From 42bc13abbce930af4a1e6a9cceca03f949b2c60c Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Fri, 19 Feb 2016 04:27:02 +0000 Subject: [PATCH 15/18] Add Gitter badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d23a57bf..e55643fb 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Alliance Auth ============ +[![Join the chat at https://gitter.im/R4stl1n/allianceauth](https://badges.gitter.im/R4stl1n/allianceauth.svg)](https://gitter.im/R4stl1n/allianceauth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + Alliance service auth to help large scale alliances manage services. Built for "The 99 Percent" open for anyone to use From 11e8e2b1d6e222a5d08ca9ba8acd9a9c96baed64 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 19 Feb 2016 15:50:53 -0500 Subject: [PATCH 16/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e55643fb..d30ed5e1 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Alliance Auth Alliance service auth to help large scale alliances manage services. Built for "The 99 Percent" open for anyone to use -[Documentation and Setup Guides](http://allianceauth.com) +[Documentation and Setup Guides](https://github.com/R4stl1n/allianceauth/wiki) [Project Website](http://r4stl1n.github.io/allianceauth/) From 5f6b4c90956f352f76749a3dc0f8294ef4e8a980 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 19 Feb 2016 04:37:54 +0000 Subject: [PATCH 17/18] Make update.sh executable --- update.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 update.sh diff --git a/update.sh b/update.sh old mode 100644 new mode 100755 From 26354751e820c605ad3abd35c7b39e85af657f06 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 19 Feb 2016 20:28:25 -0500 Subject: [PATCH 18/18] Fixes #281 --- timerboard/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/timerboard/views.py b/timerboard/views.py index fa5711c0..93c6b66c 100755 --- a/timerboard/views.py +++ b/timerboard/views.py @@ -39,7 +39,7 @@ def timer_view(request): corp_timers = Timer.objects.all().filter(corp_timer=True).filter(eve_corp=corp) else: corp_timers = [] - timer_list = Timer.objects.all() + timer_list = Timer.objects.filter(corp_timer=False) closest_timer = None if timer_list: closest_timer = \ @@ -159,4 +159,4 @@ def edit_timer(request, timer_id): } form = TimerForm(initial= data) - return render_to_response('registered/timerupdate.html', {'form':form}, context_instance=RequestContext(request)) \ No newline at end of file + return render_to_response('registered/timerupdate.html', {'form':form}, context_instance=RequestContext(request))