diff --git a/README.md b/README.md index 6140d712..213c7e0d 100755 --- a/README.md +++ b/README.md @@ -60,7 +60,6 @@ Special Permissions In Admin: auth | user | alliance_member ( Added auto by auth when a member is verified ) auth | user | group_management ( Access to add members to groups within the alliance ) - auth | user | human_resources ( Corp only access to view applications ) auth | user | jabber_broadcast ( Access to broadcast a message over jabber to own groups) auth | user | jabber_broadcast_all ( Can choose from all groups and the 'all' option when broadcasting) auth | user | blue_member ( Auto Added to people who register has a blue when adding api key) @@ -75,6 +74,13 @@ Special Permissions In Admin: auth | user | optimer_view ( Allows for an individual view fleet operations) auth | user | logging_notifications ( Generate notifications from logging) + auth | user | human_resources ( View applications to user's corp ) + hrapplications | application | delete_application ( Can delete applications ) + hrapplications | application | accept_application ( Can accept applications ) + hrapplications | application | reject_application ( Can reject applications ) + hrapplications | application | view_apis ( Can see applicant's API keys ) + hrapplicstions | applicationcomment | add_applicationcomment ( Can comment on applications ) + Active Developers Adarnof diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index e068b5a1..e2289117 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -97,15 +97,6 @@ DATABASES = { 'PASSWORD': os.environ.get('AA_DB_PHPBB3_PASSWORD', 'password'), 'HOST': os.environ.get('AA_DB_PHPBB3_HOST', '127.0.0.1'), 'PORT': os.environ.get('AA_DB_PHPBB3_PORT', '3306'), - }, - - 'mumble': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'alliance_mumble', - 'USER': os.environ.get('AA_DB_MUMBLE_USER', 'allianceserver'), - 'PASSWORD': os.environ.get('AA_DB_MUMBLE_PASSWORD', 'password'), - 'HOST': os.environ.get('AA_DB_MUMBLE_HOST', '127.0.0.1'), - 'PORT': os.environ.get('AA_DB_MUMBLE_PORT', '3306'), } } diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 4a308518..c1067210 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -64,7 +64,9 @@ urlpatterns = patterns('', # HR Application Management url(r'^hr_application_management/', 'hrapplications.views.hr_application_management_view', name="auth_hrapplications_view"), - url(r'^hr_application_create/', 'hrapplications.views.hr_application_create_view', + url(r'^hr_application_create/$', 'hrapplications.views.hr_application_create_view', + name="auth_hrapplication_create_view"), + url(r'^hr_application_create/(\d+)', 'hrapplications.views.hr_application_create_view', name="auth_hrapplication_create_view"), url(r'^hr_application_remove/(\w+)', 'hrapplications.views.hr_application_remove', name="auth_hrapplication_remove"), diff --git a/celerytask/__init__.py b/celerytask/__init__.py index e69de29b..b31856c4 100644 --- a/celerytask/__init__.py +++ b/celerytask/__init__.py @@ -0,0 +1 @@ +import signals diff --git a/celerytask/signals.py b/celerytask/signals.py new file mode 100644 index 00000000..1a65f86a --- /dev/null +++ b/celerytask/signals.py @@ -0,0 +1,29 @@ +from django.db.models.signals import m2m_changed +from django.dispatch import receiver +from django.contrib.auth.models import User +import logging +from .tasks import update_jabber_groups +from .tasks import update_mumble_groups +from .tasks import update_forum_groups +from .tasks import update_ipboard_groups +from .tasks import update_discord_groups +from authentication.models import AuthServicesInfo + +logger = logging.getLogger(__name__) + +@receiver(m2m_changed, sender=User.groups.through) +def m2m_changed_user_groups(sender, instance, action, *args, **kwargs): + logger.debug("Received m2m_changed from %s groups with action %s" % (instance, action)) + if action=="post_add" or action=="post_remove" or action=="post_clear": + logger.debug("Triggering service group update for %s" % instance) + auth, c = AuthServicesInfo.objects.get_or_create(user=instance) + if auth.jabber_username: + update_jabber_groups.delay(instance) + if auth.jabber_username: + update_jabber_groups.delay(instance) + if auth.forum_username: + update_forum_groups.delay(instance) + if auth.ipboard_username: + update_ipboard_groups.delay(instance) + if auth.discord_username: + update_discord_groups.delay(instance) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index bc2a2825..a3eea557 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -4,7 +4,6 @@ from django.contrib.auth.models import User from django.contrib.auth.models import Group from notifications import notify from celery import task -from models import SyncGroupCache from celery.task.schedules import crontab from services.managers.openfire_manager import OpenfireManager from services.managers.mumble_manager import MumbleManager @@ -31,6 +30,7 @@ from eveonline.models import EveAllianceInfo from authentication.managers import AuthServicesInfoManager from services.models import DiscordAuthToken +import evelink import time import logging @@ -53,68 +53,75 @@ def disable_member(user): def is_teamspeak3_active(): return settings.ENABLE_AUTH_TEAMSPEAK3 or settings.ENABLE_BLUE_TEAMSPEAK3 +@task def update_jabber_groups(user): logger.debug("Updating jabber groups for user %s" % user) - syncgroups = SyncGroupCache.objects.filter(user=user) authserviceinfo = AuthServicesInfo.objects.get(user=user) groups = [] - logger.debug("User %s has %s syncgroups." % (user, len(syncgroups))) - for syncgroup in syncgroups: - groups.append(str(syncgroup.groupname)) - + for group in user.groups.all(): + groups.append(str(group.name)) if len(groups) == 0: groups.append('empty') logger.debug("Updating user %s jabber groups to %s" % (user, groups)) - - OpenfireManager.update_user_groups(authserviceinfo.jabber_username, authserviceinfo.jabber_password, groups) + try: + OpenfireManager.update_user_groups(authserviceinfo.jabber_username, authserviceinfo.jabber_password, groups) + except: + logger.warn("Jabber group sync failed for %s, retrying in 10 mins" % user) + raise self.retry(countdown = 60 * 10) logger.debug("Updated user %s jabber groups." % user) - +@task def update_mumble_groups(user): logger.debug("Updating mumble groups for user %s" % user) - syncgroups = SyncGroupCache.objects.filter(user=user) authserviceinfo = AuthServicesInfo.objects.get(user=user) groups = [] - logger.debug("User %s has %s syncgroups." % (user, len(syncgroups))) - for syncgroup in syncgroups: - groups.append(str(syncgroup.groupname)) - + for group in user.groups.all(): + groups.append(str(group.name)) if len(groups) == 0: groups.append('empty') logger.debug("Updating user %s mumble groups to %s" % (user, groups)) - MumbleManager.update_groups(authserviceinfo.mumble_username, groups) + try: + MumbleManager.update_groups(authserviceinfo.mumble_username, groups) + except: + logger.warn("Mumble group sync failed for %s, retrying in 10 mins" % user) + raise self.retry(countdown = 60 * 10) logger.debug("Updated user %s mumble groups." % user) +@task def update_forum_groups(user): logger.debug("Updating forum groups for user %s" % user) - syncgroups = SyncGroupCache.objects.filter(user=user) authserviceinfo = AuthServicesInfo.objects.get(user=user) groups = [] - logger.debug("User %s has %s syncgroups." % (user, len(syncgroups))) - for syncgroup in syncgroups: - groups.append(str(syncgroup.groupname)) - + for group in user.groups.all(): + groups.append(str(group.name)) if len(groups) == 0: groups.append('empty') logger.debug("Updating user %s forum groups to %s" % (user, groups)) - Phpbb3Manager.update_groups(authserviceinfo.forum_username, groups) + try: + Phpbb3Manager.update_groups(authserviceinfo.forum_username, groups) + except: + logger.warn("Phpbb group sync failed for %s, retrying in 10 mins" % user) + raise self.retry(countdown = 60 * 10) logger.debug("Updated user %s forum groups." % user) +@task def update_ipboard_groups(user): logger.debug("Updating user %s ipboard groups." % user) - syncgroups = SyncGroupCache.objects.filter(user=user) authserviceinfo = AuthServicesInfo.objects.get(user=user) groups = [] - logger.debug("User %s has %s syncgroups." % (user, len(syncgroups))) - for syncgroup in syncgroups: - groups.append(str(syncgroup.groupname)) - + for group in user.groups.all(): + groups.append(str(group.name)) if len(groups) == 0: groups.append('empty') logger.debug("Updating user %s ipboard groups to %s" % (user, groups)) - IPBoardManager.update_groups(authserviceinfo.ipboard_username, groups) + try: + IPBoardManager.update_groups(authserviceinfo.ipboard_username, groups) + except: + logger.warn("IPBoard group sync failed for %s, retrying in 10 mins" % user) + raise self.retry(countdown = 60 * 10) logger.debug("Updated user %s ipboard groups." % user) +@task def update_teamspeak3_groups(user): logger.debug("Updating user %s teamspeak3 groups" % user) usergroups = user.groups.all() @@ -130,129 +137,23 @@ def update_teamspeak3_groups(user): Teamspeak3Manager.update_groups(authserviceinfo.teamspeak3_uid, groups) logger.debug("Updated user %s teamspeak3 groups." % user) +@task def update_discord_groups(user): logger.debug("Updating discord groups for user %s" % user) - syncgroups = SyncGroupCache.objects.filter(user=user) authserviceinfo = AuthServicesInfo.objects.get(user=user) - groups = [] - for syncgroup in syncgroups: - groups.append(str(syncgroup.groupname)) - - logger.debug("User %s has %s syncgroups." % (user, len(syncgroups))) + for group in user.groups.all(): + groups.append(str(group.name)) if len(groups) == 0: logger.debug("No syncgroups found for user. Adding empty group.") groups.append('empty') logger.debug("Updating user %s discord groups to %s" % (user, groups)) - DiscordManager.update_groups(authserviceinfo.discord_uid, groups) + try: + DiscordManager.update_groups(authserviceinfo.discord_uid, groups) + except: + logger.warn("Discord group sync failed for %s, retrying in 10 mins" % user) + raise self.retry(countdown = 60 * 10) logger.debug("Updated user %s discord groups." % user) -def create_syncgroup_for_user(user, groupname, servicename): - logger.debug("Creating syncgroupcache for user %s group %s in service %s" % (user, groupname, servicename)) - synccache = SyncGroupCache() - synccache.groupname = groupname - synccache.user = user - synccache.servicename = servicename - synccache.save() - logger.info("Created syncgroup for user %s group %s in service %s" % (user, groupname, servicename)) - - -def remove_all_syncgroups_for_service(user, servicename): - logger.debug("Removing all syncgroups for user %s service %s" % (user, servicename)) - syncgroups = SyncGroupCache.objects.filter(user=user) - logger.debug("User %s has %s syncgroups." % (user, len(syncgroups))) - for syncgroup in syncgroups: - if syncgroup.servicename == servicename: - logger.debug("Deleting syncgroups %s" % syncgroup) - syncgroup.delete() - logger.info("Removed all syncgroups for user %s service %s" % (user, servicename)) - - -def add_to_databases(user, groups, syncgroups): - logger.debug("add_to_database for user %s called. groups %s - syncgroups %s" % (user, groups, syncgroups)) - authserviceinfo = None - try: - authserviceinfo = AuthServicesInfo.objects.get(user=user) - logger.debug("Got authservicesinfo object %s" % authserviceinfo) - except: - logger.debug("No authservicesinfo object found for user %s" % user) - pass - - if authserviceinfo: - authserviceinfo = AuthServicesInfo.objects.get(user=user) - - if authserviceinfo.teamspeak3_uid and authserviceinfo.teamspeak3_uid != "": - logger.debug("Updating user TS groups.") - update_teamspeak3_groups(user) - - for group in groups: - if authserviceinfo.jabber_username and authserviceinfo.jabber_username != "": - if syncgroups.filter(groupname=group.name).filter(servicename="openfire").exists() is not True: - logger.debug("User %s has jabber username %s - missing group %s." % (user, authserviceinfo.jabber_username, group.name)) - create_syncgroup_for_user(user, group.name, "openfire") - update_jabber_groups(user) - if authserviceinfo.mumble_username and authserviceinfo.mumble_username != "": - if syncgroups.filter(groupname=group.name).filter(servicename="mumble").exists() is not True: - logger.debug("User %s has mumble username %s - missing group %s." % (user, authserviceinfo.mumble_username, group.name)) - create_syncgroup_for_user(user, group.name, "mumble") - update_mumble_groups(user) - if authserviceinfo.forum_username and authserviceinfo.forum_username != "": - if syncgroups.filter(groupname=group.name).filter(servicename="phpbb3").exists() is not True: - logger.debug("User %s has phpbb username %s - missing group %s." % (user, authserviceinfo.forum_username, group.name)) - create_syncgroup_for_user(user, group.name, "phpbb3") - update_forum_groups(user) - if authserviceinfo.ipboard_username and authserviceinfo.ipboard_username != "": - if syncgroups.filter(groupname=group.name).filter(servicename="ipboard").exists() is not True: - logger.debug("User %s has ipboard username %s - missing group %s." % (user, authserviceinfo.ipboard_username, group.name)) - create_syncgroup_for_user(user, group.name, "ipboard") - update_ipboard_groups(user) - if authserviceinfo.discord_uid and authserviceinfo.discord_uid != "": - if syncgroups.filter(groupname=group.name).filter(servicename="discord").exists() is not True: - logger.debug("User %s has discord uid %s - missing group %s." % (user, authserviceinfo.discord_uid, group.name)) - create_syncgroup_for_user(user, group.name, "discord") - update_discord_groups(user) - - -def remove_from_databases(user, groups, syncgroups): - logger.debug("remove_from_database for user %s called. groups %s - syncgroups %s" % (user, groups, syncgroups)) - authserviceinfo = None - try: - authserviceinfo = AuthServicesInfo.objects.get(user=user) - logger.debug("Got authservicesinfo object %s" % authserviceinfo) - except: - logger.debug("No authservicesinfo object found for user %s" % user) - pass - - if authserviceinfo: - update = False - for syncgroup in syncgroups: - group = groups.filter(name=syncgroup.groupname) - logger.debug("Got group %s for syncgroup %s" % (group, syncgroup)) - if not group: - logger.debug("Deleting syncgroup %s" % syncgroup) - syncgroup.delete() - update = True - - if update: - logger.debug("Syncgroups updated. Propogating to services for user %s" % user) - if authserviceinfo.jabber_username and authserviceinfo.jabber_username != "": - logger.debug("User %s has jabber username %s - updating groups." % (user, authserviceinfo.jabber_username)) - update_jabber_groups(user) - if authserviceinfo.mumble_username and authserviceinfo.mumble_username != "": - logger.debug("User %s has mumble username %s - updating groups." % (user, authserviceinfo.mumble_username)) - update_mumble_groups(user) - if authserviceinfo.forum_username and authserviceinfo.forum_username != "": - logger.debug("User %s has forum username %s - updating groups." % (user, authserviceinfo.forum_username)) - update_forum_groups(user) - if authserviceinfo.ipboard_username and authserviceinfo.ipboard_username != "": - logger.debug("User %s has ipboard username %s - updating groups." % (user, authserviceinfo.ipboard_username)) - update_ipboard_groups(user) - if authserviceinfo.teamspeak3_uid and authserviceinfo.teamspeak3_uid != "": - logger.debug("User %s has ts3 uid %s - updating groups." % (user, authserviceinfo.teamspeak3_uid)) - update_teamspeak3_groups(user) - if authserviceinfo.discord_uid and authserviceinfo.discord_uid != "": - logger.debug("User %s has discord uid %s - updating groups." % (user, authserviceinfo.discord_uid)) - update_discord_groups(user) - def assign_corp_group(auth): corp_group = None if auth.main_char_id: @@ -420,24 +321,6 @@ def set_state(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="*/10")) -def run_databaseUpdate(): - logger.debug("Starting database update.") - users = User.objects.all() - if (is_teamspeak3_active()): - logger.debug("TS3 installed. Syncing local group objects.") - Teamspeak3Manager._sync_ts_group_db() - for user in users: - logger.debug("Initiating database update for user %s" % user) - groups = user.groups.all() - logger.debug("User has groups %s" % groups) - syncgroups = SyncGroupCache.objects.filter(user=user) - logger.debug("User has syncgroups %s" % syncgroups) - add_to_databases(user, groups, syncgroups) - remove_from_databases(user, groups, syncgroups) - time.sleep(1) - # Run every 2 hours @periodic_task(run_every=crontab(minute="0", hour="*/2")) def run_discord_token_cleanup(): @@ -460,76 +343,43 @@ def refresh_api(api_key_pair): 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: - 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: + if not EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key): 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 - 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: + if not EveApiManager.check_blue_api_is_full(api_key_pair.api_id, api_key_pair.api_key): 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) - 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: + if not EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key): 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 - 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: + if not EveApiManager.check_api_is_full(api_key_pair.api_id, api_key_pair.api_key): 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) - 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_id) + if not still_valid: + 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") + else: + 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_id) 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) @@ -551,7 +401,19 @@ def run_api_refresh(): authserviceinfo, c = AuthServicesInfo.objects.get_or_create(user=user) logger.debug("User %s has api keys. Proceeding to refresh." % user) for api_key_pair in api_key_pairs: - refresh_api(api_key_pair) + try: + refresh_api(api_key_pair) + except evelink.api.APIError as e: + if int(e.code) >= 500: + logger.error("EVE API servers encountered an error. Aborting API updates") + return + elif int(e.code) == 221: + logger.warn("API server hiccup while updating %s" % api_key_pair) + else: + logger.debug("API key %s failed update with error code %s" % (api_key_pair.api_id, e.code)) + 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 failed validation with code %s. It and its associated characters have been deleted." % (api_key_pair.api_id, e.code), level="danger") # 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)) @@ -625,178 +487,180 @@ def run_corp_update(): logger.warn("Aborted updating corp and alliance models: API server unreachable") return standing_level = 'alliance' - - # get corp info for owning corp if required - ownercorpinfo = {} - if settings.IS_CORP: - standing_level = 'corp' - logger.debug("Getting information for owning corp with id %s" % settings.CORP_ID) - ownercorpinfo = EveApiManager.get_corporation_information(settings.CORP_ID) - if not ownercorpinfo: - logger.error("Failed to retrieve corp info for owning corp id %s - bad corp id?" % settings.CORP_ID) - return - - # check if we need to update an alliance model - alliance_id = '' - if ownercorpinfo and ownercorpinfo['alliance']['id']: - alliance_id = ownercorpinfo['alliance']['id'] - elif settings.IS_CORP is False: - alliance_id = settings.ALLIANCE_ID - - # get and create alliance info for owning alliance if required - alliance = None - if alliance_id: - logger.debug("Getting information for owning alliance with id %s" % alliance_id) - ownerallianceinfo = EveApiManager.get_alliance_information(alliance_id) - if not ownerallianceinfo: - logger.error("Failed to retrieve corp info for owning alliance id %s - bad alliance id?" % alliance_id) - return - if EveAllianceInfo.objects.filter(alliance_id=ownerallianceinfo['id']).exists(): - logger.debug("Updating existing owner alliance model with id %s" % alliance_id) - EveManager.update_alliance_info(ownerallianceinfo['id'], ownerallianceinfo['executor_id'], ownerallianceinfo['member_count'], False) - else: - populate_alliance(alliance_id) - alliance = EveAllianceInfo.objects.get(alliance_id=alliance_id) - - # create corp info for owning corp if required - if ownercorpinfo: - if EveCorporationInfo.objects.filter(corporation_id=ownercorpinfo['id']).exists(): - logger.debug("Updating existing owner corp model with id %s" % ownercorpinfo['id']) - EveManager.update_corporation_info(ownercorpinfo['id'], ownercorpinfo['members']['current'], alliance, False) - else: - logger.info("Creating model for owning corp with id %s" % ownercorpinfo['id']) - EveManager.create_corporation_info(ownercorpinfo['id'], ownercorpinfo['name'], ownercorpinfo['ticker'], + try: + # get corp info for owning corp if required + ownercorpinfo = {} + if settings.IS_CORP: + standing_level = 'corp' + logger.debug("Getting information for owning corp with id %s" % settings.CORP_ID) + ownercorpinfo = EveApiManager.get_corporation_information(settings.CORP_ID) + if not ownercorpinfo: + logger.error("Failed to retrieve corp info for owning corp id %s - bad corp id?" % settings.CORP_ID) + return + + # check if we need to update an alliance model + alliance_id = '' + if ownercorpinfo and ownercorpinfo['alliance']['id']: + alliance_id = ownercorpinfo['alliance']['id'] + elif settings.IS_CORP is False: + alliance_id = settings.ALLIANCE_ID + + # get and create alliance info for owning alliance if required + alliance = None + if alliance_id: + logger.debug("Getting information for owning alliance with id %s" % alliance_id) + ownerallianceinfo = EveApiManager.get_alliance_information(alliance_id) + if not ownerallianceinfo: + logger.error("Failed to retrieve corp info for owning alliance id %s - bad alliance id?" % alliance_id) + return + if EveAllianceInfo.objects.filter(alliance_id=ownerallianceinfo['id']).exists(): + logger.debug("Updating existing owner alliance model with id %s" % alliance_id) + EveManager.update_alliance_info(ownerallianceinfo['id'], ownerallianceinfo['executor_id'], ownerallianceinfo['member_count'], False) + else: + populate_alliance(alliance_id) + alliance = EveAllianceInfo.objects.get(alliance_id=alliance_id) + + # create corp info for owning corp if required + if ownercorpinfo: + if EveCorporationInfo.objects.filter(corporation_id=ownercorpinfo['id']).exists(): + logger.debug("Updating existing owner corp model with id %s" % ownercorpinfo['id']) + EveManager.update_corporation_info(ownercorpinfo['id'], ownercorpinfo['members']['current'], alliance, False) + else: + logger.info("Creating model for owning corp with id %s" % ownercorpinfo['id']) + EveManager.create_corporation_info(ownercorpinfo['id'], ownercorpinfo['name'], ownercorpinfo['ticker'], ownercorpinfo['members']['current'], False, alliance) - # validate and create corp models for member corps of owning alliance - if alliance: - current_corps = EveCorporationInfo.objects.filter(alliance=alliance) - for corp in current_corps: - if corp.corporation_id in ownerallianceinfo['member_corps'] is False: - logger.info("Corp %s is no longer in owning alliance %s - updating model." % (corp, alliance)) - corp.alliance = None - corp.save() - for member_corp in ownerallianceinfo['member_corps']: - if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists(): - corp = EveCorporationInfo.objects.get(corporation_id=member_corp) - if corp.alliance == alliance is not True: - logger.info("Associating corp %s with owning alliance %s" % (corp, alliance)) - corp.alliance = alliance + # validate and create corp models for member corps of owning alliance + if alliance: + current_corps = EveCorporationInfo.objects.filter(alliance=alliance) + for corp in current_corps: + if corp.corporation_id in ownerallianceinfo['member_corps'] is False: + logger.info("Corp %s is no longer in owning alliance %s - updating model." % (corp, alliance)) + corp.alliance = None corp.save() - else: - corpinfo = EveApiManager.get_corporation_information(member_corp) - logger.info("Creating model for owning alliance member corp with id %s" % corpinfo['id']) - EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'], + for member_corp in ownerallianceinfo['member_corps']: + if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists(): + corp = EveCorporationInfo.objects.get(corporation_id=member_corp) + if corp.alliance == alliance is not True: + logger.info("Associating corp %s with owning alliance %s" % (corp, alliance)) + corp.alliance = alliance + corp.save() + else: + corpinfo = EveApiManager.get_corporation_information(member_corp) + logger.info("Creating model for owning alliance member corp with id %s" % corpinfo['id']) + EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'], corpinfo['members']['current'], False, alliance) - # update existing corp models - for corp in EveCorporationInfo.objects.all(): - update_corp.delay(corp.corporation_id) + # update existing corp models + for corp in EveCorporationInfo.objects.all(): + update_corp.delay(corp.corporation_id) - # update existing alliance models - for alliance in EveAllianceInfo.objects.all(): - update_alliance.delay(alliance.alliance_id) + # update existing alliance models + for alliance in EveAllianceInfo.objects.all(): + update_alliance.delay(alliance.alliance_id) - # create standings - standings = EveApiManager.get_corp_standings() - if standings: - standings = standings[standing_level] - for standing in standings: - if int(standings[standing]['standing']) >= settings.BLUE_STANDING: - logger.debug("Standing %s meets threshold" % standing) - if EveApiManager.check_if_id_is_alliance(standing): - logger.debug("Standing %s is an alliance" % standing) - if EveAllianceInfo.objects.filter(alliance_id=standing).exists(): - alliance = EveAllianceInfo.objects.get(alliance_id=standing) - if alliance.is_blue is not True: - logger.info("Updating alliance %s as blue" % alliance) - alliance.is_blue = True - alliance.save() - else: - populate_alliance(standing, blue=True) - elif EveApiManager.check_if_id_is_corp(standing): - logger.debug("Standing %s is a corp" % standing) - if EveCorporationInfo.objects.filter(corporation_id=standing).exists(): - corp = EveCorporationInfo.objects.get(corporation_id=standing) - if corp.is_blue is not True: - logger.info("Updating corp %s as blue" % corp) - corp.is_blue = True - corp.save() - else: - logger.info("Creating model for blue corp with id %s" % standing) - corpinfo = EveApiManager.get_corporation_information(standing) - corp_alliance = None - if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists(): - logger.debug("New corp model for standing %s has existing alliance model" % standing) - corp_alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id']) - EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'], + # create standings + standings = EveApiManager.get_corp_standings() + if standings: + standings = standings[standing_level] + for standing in standings: + if int(standings[standing]['standing']) >= settings.BLUE_STANDING: + logger.debug("Standing %s meets threshold" % standing) + if EveApiManager.check_if_id_is_alliance(standing): + logger.debug("Standing %s is an alliance" % standing) + if EveAllianceInfo.objects.filter(alliance_id=standing).exists(): + alliance = EveAllianceInfo.objects.get(alliance_id=standing) + if alliance.is_blue is not True: + logger.info("Updating alliance %s as blue" % alliance) + alliance.is_blue = True + alliance.save() + else: + populate_alliance(standing, blue=True) + elif EveApiManager.check_if_id_is_corp(standing): + logger.debug("Standing %s is a corp" % standing) + if EveCorporationInfo.objects.filter(corporation_id=standing).exists(): + corp = EveCorporationInfo.objects.get(corporation_id=standing) + if corp.is_blue is not True: + logger.info("Updating corp %s as blue" % corp) + corp.is_blue = True + corp.save() + else: + logger.info("Creating model for blue corp with id %s" % standing) + corpinfo = EveApiManager.get_corporation_information(standing) + corp_alliance = None + if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists(): + logger.debug("New corp model for standing %s has existing alliance model" % standing) + corp_alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id']) + EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'], corpinfo['members']['current'], True, corp_alliance) - # update alliance standings - for alliance in EveAllianceInfo.objects.filter(is_blue=True): - if int(alliance.alliance_id) in standings: - if float(standings[int(alliance.alliance_id)]['standing']) < float(settings.BLUE_STANDING): - logger.info("Alliance %s no longer meets minimum blue standing threshold" % alliance) + # update alliance standings + for alliance in EveAllianceInfo.objects.filter(is_blue=True): + if int(alliance.alliance_id) in standings: + if float(standings[int(alliance.alliance_id)]['standing']) < float(settings.BLUE_STANDING): + logger.info("Alliance %s no longer meets minimum blue standing threshold" % alliance) + alliance.is_blue = False + alliance.save() + else: + logger.info("Alliance %s no longer in standings" % alliance) alliance.is_blue = False alliance.save() - else: - logger.info("Alliance %s no longer in standings" % alliance) - alliance.is_blue = False - alliance.save() - - # update corp standings - for corp in EveCorporationInfo.objects.filter(is_blue=True): - if int(corp.corporation_id) in standings: - if float(standings[int(corp.corporation_id)]['standing']) < float(settings.BLUE_STANDING): - logger.info("Corp %s no longer meets minimum blue standing threshold" % corp) - corp.is_blue = False - corp.save() - else: - if corp.alliance: - if corp.alliance.is_blue is False: - logger.info("Corp %s and its alliance %s are no longer blue" % (corp, corp.alliance)) + + # update corp standings + for corp in EveCorporationInfo.objects.filter(is_blue=True): + if int(corp.corporation_id) in standings: + if float(standings[int(corp.corporation_id)]['standing']) < float(settings.BLUE_STANDING): + logger.info("Corp %s no longer meets minimum blue standing threshold" % corp) corp.is_blue = False corp.save() else: - logger.info("Corp %s is no longer blue" % corp) - corp.is_blue = False - corp.save() + if corp.alliance: + if corp.alliance.is_blue is False: + logger.info("Corp %s and its alliance %s are no longer blue" % (corp, corp.alliance)) + corp.is_blue = False + corp.save() + else: + logger.info("Corp %s is no longer blue" % corp) + corp.is_blue = False + corp.save() - # delete unnecessary alliance models - for alliance in EveAllianceInfo.objects.filter(is_blue=False): - logger.debug("Checking to delete alliance %s" % alliance) - if settings.IS_CORP is False: - if alliance.alliance_id == settings.ALLIANCE_ID is False: - logger.info("Deleting unnecessary alliance model %s" % alliance) - alliance.delete() - else: - if alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists() is False: - logger.info("Deleting unnecessary alliance model %s" % alliance) - alliance.delete() - - # delete unnecessary corp models - for corp in EveCorporationInfo.objects.filter(is_blue=False): - logger.debug("Checking to delete corp %s" % corp) - if settings.IS_CORP is False: - if corp.alliance: - logger.debug("Corp %s has alliance %s" % (corp, corp.alliance)) - if corp.alliance.alliance_id == settings.ALLIANCE_ID is False: - logger.info("Deleting unnecessary corp model %s" % corp) - corp.delete() + # delete unnecessary alliance models + for alliance in EveAllianceInfo.objects.filter(is_blue=False): + logger.debug("Checking to delete alliance %s" % alliance) + if settings.IS_CORP is False: + if alliance.alliance_id == settings.ALLIANCE_ID is False: + logger.info("Deleting unnecessary alliance model %s" % alliance) + alliance.delete() else: - logger.info("Deleting unnecessary corp model %s" % corp) - corp.delete() - else: - if corp.corporation_id != settings.CORP_ID: - logger.debug("Corp %s is not owning corp" % corp) + if alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists() is False: + logger.info("Deleting unnecessary alliance model %s" % alliance) + alliance.delete() + + # delete unnecessary corp models + for corp in EveCorporationInfo.objects.filter(is_blue=False): + logger.debug("Checking to delete corp %s" % corp) + if settings.IS_CORP is False: if corp.alliance: logger.debug("Corp %s has alliance %s" % (corp, corp.alliance)) - if corp.alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists() is False: + if corp.alliance.alliance_id == settings.ALLIANCE_ID is False: logger.info("Deleting unnecessary corp model %s" % corp) corp.delete() else: logger.info("Deleting unnecessary corp model %s" % corp) corp.delete() else: - logger.debug("Corp %s is owning corp" % corp) + if corp.corporation_id != settings.CORP_ID: + logger.debug("Corp %s is not owning corp" % corp) + if corp.alliance: + logger.debug("Corp %s has alliance %s" % (corp, corp.alliance)) + if corp.alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists() is False: + logger.info("Deleting unnecessary corp model %s" % corp) + corp.delete() + else: + logger.info("Deleting unnecessary corp model %s" % corp) + corp.delete() + else: + logger.debug("Corp %s is owning corp" % corp) + except evelink.api.APIError as e: + logger.error("Model update failed with error code %s" % e.code) diff --git a/eveonline/forms.py b/eveonline/forms.py index d81e1cf5..2cf62974 100644 --- a/eveonline/forms.py +++ b/eveonline/forms.py @@ -4,6 +4,7 @@ from django.conf import settings from services.managers.eve_api_manager import EveApiManager from eveonline.managers import EveManager from eveonline.models import EveCharacter +import evelink from celerytask.tasks import determine_membership_by_character @@ -28,27 +29,34 @@ class UpdateKeyForm(forms.Form): super(UpdateKeyForm, self).clean() if 'api_id' in self.cleaned_data and 'api_key' in self.cleaned_data: - 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) - 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) + try: + 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) + 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 must meet member requirements') - 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 must meet blue requirements') - return self.cleaned_data + 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 must meet member requirements') + 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 must meet blue requirements') + return self.cleaned_data + except evelink.api.APIError as e: + logger.debug("Got error code %s while validating API %s" % (e.code, self.cleaned_data['api_id'])) + if int(e.code) in [221, 222]: + raise forms.ValidationError("API key failed validation") + else: + raise forms.ValidationError("Failed to reach API servers") diff --git a/hrapplications/admin.py b/hrapplications/admin.py index b150827c..5b7e89aa 100755 --- a/hrapplications/admin.py +++ b/hrapplications/admin.py @@ -1,7 +1,13 @@ from django.contrib import admin -from models import HRApplication -from models import HRApplicationComment +from models import Application +from models import ApplicationQuestion +from models import ApplicationForm +from models import ApplicationResponse +from models import ApplicationComment -admin.site.register(HRApplication) -admin.site.register(HRApplicationComment) \ No newline at end of file +admin.site.register(Application) +admin.site.register(ApplicationComment) +admin.site.register(ApplicationQuestion) +admin.site.register(ApplicationForm) +admin.site.register(ApplicationResponse) diff --git a/hrapplications/forms.py b/hrapplications/forms.py index 7d1ad0e7..20bf91ee 100755 --- a/hrapplications/forms.py +++ b/hrapplications/forms.py @@ -1,33 +1,7 @@ from django import forms -from django.conf import settings - -from eveonline.models import EveCorporationInfo - -class HRApplicationForm(forms.Form): - allchoices = [] - - if settings.IS_CORP: - corp = EveCorporationInfo.objects.get(corporation_id=settings.CORP_ID) - allchoices.append((str(corp.corporation_id), str(corp.corporation_name))) - else: - for corp in EveCorporationInfo.objects.all(): - if corp.alliance is not None: - if corp.alliance.alliance_id == settings.ALLIANCE_ID: - allchoices.append((str(corp.corporation_id), str(corp.corporation_name))) - - character_name = forms.CharField(max_length=254, required=True, label="Main Character Name") - full_api_id = forms.CharField(max_length=254, required=True, label="API ID") - full_api_key = forms.CharField(max_length=254, required=True, label="API Verification Code") - corp = forms.ChoiceField(choices=allchoices, required=True, label="Corp") - is_a_spi = forms.ChoiceField(choices=[('Yes', 'Yes'), ('No', 'No')], required=True, label='Are you a spy?') - about = forms.CharField(widget=forms.Textarea, required=False, label="About You") - extra = forms.CharField(widget=forms.Textarea, required=False, label="Extra Application Info") - class HRApplicationCommentForm(forms.Form): - app_id = forms.CharField(widget=forms.TextInput(attrs={'readonly': 'True'})) comment = forms.CharField(widget=forms.Textarea, required=False, label="Comment", max_length=254) - class HRApplicationSearchForm(forms.Form): search_string = forms.CharField(max_length=254, required=True, label="Search String") diff --git a/hrapplications/models.py b/hrapplications/models.py index 37e55459..230c8c18 100755 --- a/hrapplications/models.py +++ b/hrapplications/models.py @@ -3,8 +3,91 @@ from django.contrib.auth.models import User from eveonline.models import EveCharacter from eveonline.models import EveCorporationInfo +from eveonline.models import EveApiKeyPair +from authentication.models import AuthServicesInfo + +class ApplicationQuestion(models.Model): + title = models.CharField(max_length=100) + help_text = models.CharField(max_length=254, blank=True, null=True) + + def __str__(self): + return "Question: " + self.title + +class ApplicationForm(models.Model): + questions = models.ManyToManyField(ApplicationQuestion) + corp = models.OneToOneField(EveCorporationInfo) + + def __str__(self): + return str(self.corp) + +class Application(models.Model): + form = models.ForeignKey(ApplicationForm, on_delete=models.CASCADE, related_name='applications') + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications') + approved = models.NullBooleanField(blank=True, null=True, default=None) + reviewer = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True) + reviewer_character = models.ForeignKey(EveCharacter, on_delete=models.SET_NULL, blank=True, null=True) + created = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return str(self.user) + " Application To " + str(self.form) + + class Meta: + permissions = (('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'), ('view_apis', 'Can view applicant APIs'),) + unique_together = ('form', 'user') + + @property + def main_character(self): + try: + auth = AuthServicesInfo.objects.get(user=self.user) + char = EveCharacter.objects.get(character_id=auth.main_char_id) + return char + except: + return None + + @property + def characters(self): + return EveCharacter.objects.filter(user=self.user) + + @property + def apis(self): + return EveApiKeyPair.objects.filter(user=self.user) + + @property + def reviewer_str(self): + if self.reviewer_character: + return str(self.reviewer_character) + elif self.reviewer: + return "User " + str(self.reviewer) + else: + return None +class ApplicationResponse(models.Model): + question = models.ForeignKey(ApplicationQuestion, on_delete=models.CASCADE) + application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='responses') + answer = models.TextField() + + def __str__(self): + return str(self.application) + " Answer To " + str(self.question) + + class Meta: + unique_together = ('question', 'application') + +class ApplicationComment(models.Model): + application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='comments') + user = models.ForeignKey(User, on_delete=models.CASCADE) + text = models.TextField() + created = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return str(self.user) + " comment on " + str(self.application) + +################ +# Legacy Models +################ +# Can't delete or evolutions explodes. +# They do nothing. +################ class HRApplication(models.Model): character_name = models.CharField(max_length=254, default="") full_api_id = models.CharField(max_length=254, default="") diff --git a/hrapplications/views.py b/hrapplications/views.py index 998be473..8e82acb8 100755 --- a/hrapplications/views.py +++ b/hrapplications/views.py @@ -1,12 +1,17 @@ from django.template import RequestContext -from django.shortcuts import render_to_response +from django.shortcuts import render_to_response, get_object_or_404, redirect from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import login_required +from django.contrib.auth.decorators import user_passes_test from django.shortcuts import HttpResponseRedirect from notifications import notify from models import HRApplication from models import HRApplicationComment -from forms import HRApplicationForm +from models import ApplicationForm +from models import Application +from models import ApplicationQuestion +from models import ApplicationResponse +from models import ApplicationComment from forms import HRApplicationCommentForm from forms import HRApplicationSearchForm from eveonline.models import EveCorporationInfo @@ -20,195 +25,177 @@ import logging logger = logging.getLogger(__name__) +def create_application_test(user): + auth, c = AuthServicesInfo.objects.get_or_create(user=user) + if auth.main_char_id: + return True + else: + return False + @login_required def hr_application_management_view(request): logger.debug("hr_application_management_view called by user %s" % request.user) - personal_app = None - corp_applications = None - + corp_applications = [] + finished_corp_applications = [] + auth_info, c = AuthServicesInfo.objects.get_or_create(user=request.user) + main_char = None + if auth_info.main_char_id: + try: + main_char = EveCharacter.objects.get(character_id=auth_info.main_char_id) + except: + pass if request.user.is_superuser: - logger.debug("User %s is superuser: returning all applications." % request.user) - corp_applications = HRApplication.objects.all() - else: - # Get the corp the member is in - auth_info = AuthServicesInfo.objects.get(user=request.user) - if auth_info.main_char_id != "": - try: - main_corp_id = EveManager.get_charater_corporation_id_by_id(auth_info.main_char_id) - main_alliance_id = EveManager.get_charater_alliance_id_by_id(auth_info.main_char_id) - if (settings.IS_CORP and main_corp_id == settings.CORP_ID) or (not settings.IS_CORP and main_alliance_id == settings.ALLIANCE_ID): - main_char = EveCharacter.objects.get(character_id=auth_info.main_char_id) - if EveCorporationInfo.objects.filter(corporation_id=main_char.corporation_id).exists(): - corp = EveCorporationInfo.objects.get(corporation_id=main_char.corporation_id) - corp_applications = HRApplication.objects.filter(corp=corp).filter(approved_denied=None) - else: - corp_applications = None - else: - corp_applications = None - except: - logger.error("Unable to determine user %s main character id %s corp. Returning no corp hrapplications." % (request.user, auth_info.main_char_id)) - corp_applications = None - context = {'personal_apps': HRApplication.objects.all().filter(user=request.user), - 'applications': corp_applications, - 'search_form': HRApplicationSearchForm()} - - return render_to_response('registered/hrapplicationmanagement.html', - context, context_instance=RequestContext(request)) - + corp_applications = Application.objects.filter(approved=None) + elif request.user.has_perm('auth.human_resources') and main_char: + if ApplicationForm.objects.filter(corp__corporation_id=main_char.corporation_id).exists(): + app_form = ApplicationForm.objects.get(corp__corporation_id=main_char.corporation_id) + corp_applications = Application.objects.filter(form=app_form).filter(approved=None) + finished_corp_applications = Application.objects.filter(form=app_form).filter(approved__in=[True, False]) + logger.debug("Retrieved %s personal, %s corp applications for %s" % (len(request.user.applications.all()), len(corp_applications), request.user)) + context = { + 'personal_apps': request.user.applications.all(), + 'applications': corp_applications, + 'finished_applications': finished_corp_applications, + 'search_form': HRApplicationSearchForm(), + 'create': create_application_test(request.user) + } + return render_to_response('registered/hrapplicationmanagement.html', context, context_instance=RequestContext(request)) @login_required -def hr_application_create_view(request): - logger.debug("hr_application_create_view called by user %s" % request.user) - success = False - - if request.method == 'POST': - form = HRApplicationForm(request.POST) - logger.debug("Request type POST with form valid: %s" % form.is_valid()) - if form.is_valid(): - application = HRApplication() - application.user = request.user - application.character_name = form.cleaned_data['character_name'] - application.full_api_id = form.cleaned_data['full_api_id'] - application.full_api_key = form.cleaned_data['full_api_key'] - application.corp = EveCorporationInfo.objects.get(corporation_id=form.cleaned_data['corp']) - application.is_a_spi = form.cleaned_data['is_a_spi'] - application.about = form.cleaned_data['about'] - application.extra = form.cleaned_data['extra'] - application.save() - success = True - logger.info("Created HRApplication for user %s to corp %s" % (request.user, application.corp)) +@user_passes_test(create_application_test) +def hr_application_create_view(request, form_id=None): + if form_id: + app_form = get_object_or_404(ApplicationForm, id=form_id) + if request.method == "POST": + if Application.objects.filter(user=request.user).filter(form=app_form).exists(): + logger.warn("User %s attempting to duplicate application to %s" % (request.user, app_form.corp)) + else: + application = Application(user=request.user, form=app_form) + application.save() + for question in app_form.questions.all(): + response = ApplicationResponse(question=question, application=application) + response.answer = request.POST.get(str(question.pk), "Failed to retrieve answer provided by applicant.") + response.save() + logger.info("%s created %s" % (request.user, application)) + return redirect('auth_hrapplications_view') + else: + questions = app_form.questions.all() + return render_to_response('registered/hrapplicationcreate.html', {'questions':questions, 'corp':app_form.corp}, context_instance=RequestContext(request)) else: - logger.debug("Providing empty form.") - form = HRApplicationForm() - - context = {'form': form, 'success': success} - return render_to_response('registered/hrcreateapplication.html', - context, context_instance=RequestContext(request)) - + choices = [] + for app_form in ApplicationForm.objects.all(): + if not Application.objects.filter(user=request.user).filter(form=app_form).exists(): + choices.append((app_form.id, app_form.corp.corporation_name)) + return render_to_response('registered/hrapplicationcorpchoice.html', {'choices':choices}, context_instance=RequestContext(request)) @login_required def hr_application_personal_view(request, app_id): logger.debug("hr_application_personal_view called by user %s for app id %s" % (request.user, app_id)) - if HRApplication.objects.filter(id=app_id).exists(): - application = HRApplication.objects.get(id=app_id) - logger.debug("Got application id %s: %s" % (app_id, application)) - if application.user != request.user: - logger.warn("HRApplication id %s user %s does not match request user %s - returning blank application." % (app_id, application.user, request.user)) - application = HRApplication() + app = get_object_or_404(Application, pk=app_id) + if app.user == request.user: + context = { + 'app': app, + 'responses': ApplicationResponse.objects.filter(application=app), + 'buttons': False, + 'comments': ApplicationComment.objects.filter(application=app), + 'comment_form': HRApplicationCommentForm(), + 'apis': [], + } + return render_to_response('registered/hrapplicationview.html', context, context_instance=RequestContext(request)) else: - logger.error("Unable to locate HRApplication matching id %s - returning blank application to user %s" % (app_id, request.user)) - application = HRApplication() - context = {'application': application} - - return render_to_response('registered/hrapplicationview.html', - context, context_instance=RequestContext(request)) - + logger.warn("User %s not authorized to view %s" % (request.user, app)) + return redirect('auth_hrapplications_view') + @login_required def hr_application_personal_removal(request, app_id): logger.debug("hr_application_personal_removal called by user %s for app id %s" % (request.user, app_id)) - if HRApplication.objects.filter(id=app_id).exists(): - application = HRApplication.objects.get(id=app_id) - if application.user == request.user: - application.delete() - logger.info("Deleted HRApplication with id %s for user %s to corp %s" % (app_id, request.user, application.corp)) + app = get_object_or_404(Application, pk=app_id) + if app.user == request.user: + if app.accepted == None: + logger.info("User %s deleting %s" % (request.user, app)) + app.delete() else: - logger.error("HRapplication id %s user %s does not match request user %s - refusing to delete." % (app_id, application.user, request.user)) - return HttpResponseRedirect("/hr_application_management/") - + logger.warn("User %s attempting to delete reviewed app %s" % (request.user, app)) + else: + logger.warn("User %s not authorized to delete %s" % (request.user, app)) + return redirect('auth_hrapplications_view') @login_required @permission_required('auth.human_resources') def hr_application_view(request, app_id): logger.debug("hr_application_view called by user %s for app id %s" % (request.user, app_id)) + app = get_object_or_404(Application, pk=app_id) if request.method == 'POST': - form = HRApplicationCommentForm(request.POST) - logger.debug("Request type POST contains form valid: %s" % form.is_valid()) - if form.is_valid(): - auth_info = AuthServicesInfo.objects.get(user=request.user) - - comment = HRApplicationComment() - comment.application = HRApplication.objects.get(id=int(form.cleaned_data['app_id'])) - comment.commenter_user = request.user - comment.commenter_character = EveCharacter.objects.get(character_id=auth_info.main_char_id) - comment.comment = form.cleaned_data['comment'] - comment.save() - logger.info("Saved comment by user %s to hrapplication %s" % (request.user, comment.application)) - + if request.user.has_perm('hrapplications.add_applicationcomment'): + form = HRApplicationCommentForm(request.POST) + logger.debug("Request type POST contains form valid: %s" % form.is_valid()) + if form.is_valid(): + comment = ApplicationComment() + comment.application = app + comment.user = request.user + comment.text = form.cleaned_data['comment'] + comment.save() + logger.info("Saved comment by user %s to %s" % (request.user, app)) + else: + logger.warn("User %s does not have permission to add ApplicationComments" % request.user) else: logger.debug("Returning blank HRApplication comment form.") form = HRApplicationCommentForm() - - if HRApplication.objects.filter(id=app_id).exists(): - application = HRApplication.objects.get(id=app_id) - comments = HRApplicationComment.objects.all().filter(application=application) - logger.debug("Retrieved hrpplication id %s on behalf of user %s with comments %s" % (app_id, request.user, len(comments))) - else: - application = HRApplication() - comments = [] - logger.error("HRAppllication with id %s not found - returning blank applicatin to user %s" % request.user) - - context = {'application': application, 'comments': comments, 'comment_form': form} - - return render_to_response('registered/hrapplicationview.html', - context, context_instance=RequestContext(request)) + apis = [] + if request.user.has_perm('hrapplications.view_apis'): + apis = app.apis + context = { + 'app': app, + 'responses': ApplicationResponse.objects.filter(application=app), + 'buttons': True, + 'apis': apis, + 'comments': ApplicationComment.objects.filter(application=app), + 'comment_form': form, + } + return render_to_response('registered/hrapplicationview.html', context, context_instance=RequestContext(request)) @login_required @permission_required('auth.human_resources') +@permission_required('hrapplications.delete_application') def hr_application_remove(request, app_id): logger.debug("hr_application_remove called by user %s for app id %s" % (request.user, app_id)) - if HRApplication.objects.filter(id=app_id).exists(): - 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)) - else: - logger.error("Unable to delete HRApplication with id %s on behalf of user %s: application not found." % (app_id, request.user)) - - return HttpResponseRedirect("/hr_application_management/") - + app = get_object_or_404(Application, pk=app_id) + logger.info("User %s deleting %s" % (request.user, app)) + app.delete() + notify(app.user, "Application Deleted", message="Your application to %s was deleted." % app.form.corp) + return redirect('auth_hrapplications_view') @login_required @permission_required('auth.human_resources') +@permission_required('hrapplications.approve_application') def hr_application_approve(request, app_id): logger.debug("hr_application_approve called by user %s for app id %s" % (request.user, app_id)) - if HRApplication.objects.filter(id=app_id).exists(): - auth_info = AuthServicesInfo.objects.get(user=request.user) - application = HRApplication.objects.get(id=app_id) - application.approved_denied = True - application.reviewer_user = request.user - 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") + app = get_object_or_404(Application, pk=app_id) + if request.user.is_superuser or request.user == app.reviewer: + logger.info("User %s approving %s" % (request.user, app)) + app.approved = True + app.save() + notify(app.user, "Application Accepted", message="Your application to %s has been approved." % app.form.corp, level="success") else: - logger.error("User %s unable to approve HRApplication id %s - hrapplication with that id not found." % (request.user, app_id)) - - return HttpResponseRedirect("/hr_application_management/") - + logger.warn("User %s not authorized to approve %s" % (request.user, app)) + return redirect('auth_hrapplications_view') @login_required @permission_required('auth.human_resources') +@permission_required('hrapplications.reject_application') def hr_application_reject(request, app_id): logger.debug("hr_application_reject called by user %s for app id %s" % (request.user, app_id)) - if HRApplication.objects.filter(id=app_id).exists(): - auth_info = AuthServicesInfo.objects.get(user=request.user) - application = HRApplication.objects.get(id=app_id) - application.approved_denied = False - application.reviewer_user = request.user - 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") + app = get_object_or_404(Application, pk=app_id) + if request.user.is_superuser or request.user == app.reviewer: + logger.info("User %s rejecting %s" % (request.user, app)) + app.approved = False + app.save() + notify(app.user, "Application Rejected", message="Your application to %s has been rejected." % app.form.corp, level="danger") else: - logger.error("User %s unable to reject HRApplication id %s - hrapplication with that id not found." % (request.user, app_id)) - - return HttpResponseRedirect("/hr_application_management/") - + logger.warn("User %s not authorized to reject %s" % (request.user, app)) + return redirect('auth_hrapplications_view') @login_required @permission_required('auth.human_resources') @@ -218,16 +205,37 @@ def hr_application_search(request): form = HRApplicationSearchForm(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'] - applications = [] + searchstring = form.cleaned_data['search_string'].lower() + applications = set([]) logger.debug("Searching for application with character name %s for user %s" % (searchstring, request.user)) - - for application in HRApplication.objects.all(): - if searchstring in application.character_name: - applications.append(application) - logger.info("Found %s HRApplications for user %s matching search string %s" % (len(applications), request.user, searchstring)) + app_list = [] + if request.user.is_superuser: + app_list = Application.objects.all() + else: + auth_info = AuthServicesInfo.objects.get(user=request.user) + try: + character = EveCharacter.objects.get(character_id=auth_info.main_char_id) + app_list = Application.objects.filter(form__corp__corporation_id=character.corporation_id) + except: + logger.warn("User %s missing main character model: unable to filter applications to search" % request.user) + for application in app_list: + if application.main_character: + if searchstring in application.main_character.character_name.lower(): + applications.add(application) + if searchstring in application.main_character.corporation_name.lower(): + applications.add(application) + if searchstring in application.main_character.alliance_name.lower():\ + applications.add(application) + for character in application.characters: + if searchstring in character.character_name.lower(): + applications.add(application) + if searchstring in character.corporation_name.lower(): + applications.add(application) + if searchstring in character.alliance_name.lower(): + applications.add(application) + if searchstring in application.user.username.lower(): + applications.add(application) + logger.info("Found %s Applications for user %s matching search string %s" % (len(applications), request.user, searchstring)) context = {'applications': applications, 'search_form': HRApplicationSearchForm()} @@ -243,19 +251,23 @@ def hr_application_search(request): logger.debug("Returning empty search form for user %s" % request.user) return HttpResponseRedirect("/hr_application_management/") - @login_required @permission_required('auth.human_resources') def hr_application_mark_in_progress(request, app_id): logger.debug("hr_application_mark_in_progress called by user %s for app id %s" % (request.user, app_id)) - if HRApplication.objects.filter(id=app_id).exists(): + app = get_object_or_404(Application, pk=app_id) + if not app.reviewer: + logger.info("User %s marking %s in progress" % (request.user, app)) auth_info = AuthServicesInfo.objects.get(user=request.user) - application = HRApplication.objects.get(id=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)) + try: + character = EveCharacter.objects.get(character_id=auth_info.main_char_id) + except: + logger.warn("User %s marking %s in review has no main character" % (request.user, app)) + character = None + app.reviewer = request.user + app.reviewer_character = character + app.save() + notify(app.user, "Application In Progress", message="Your application to %s is being reviewed by %s" % (app.form.corp, app.reviewer_str)) else: - logger.error("Unable to mark HRApplication id %s in progress by user %s - hrapplication matching id not found." % (app_id, request.user)) - + logger.warn("User %s unable to mark %s in progress: already being reviewed by %s" % (request.user, app, app.reviewer)) return HttpResponseRedirect("/hr_application_view/" + str(app_id)) diff --git a/requirements.txt b/requirements.txt index b6bf0a46..71b65d17 100755 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ evelink dnspython passlib requests>=2.9.1 -#requests_cache +zeroc-ice # Django Stuff # django==1.6.5 diff --git a/services/admin.py b/services/admin.py index 8b736274..bfca9f2c 100644 --- a/services/admin.py +++ b/services/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from .models import AuthTS from .models import DiscordAuthToken +from .models import MumbleUser class AuthTSgroupAdmin(admin.ModelAdmin): fields = ['auth_group','ts_group'] @@ -9,3 +10,5 @@ class AuthTSgroupAdmin(admin.ModelAdmin): admin.site.register(AuthTS, AuthTSgroupAdmin) admin.site.register(DiscordAuthToken) + +admin.site.register(MumbleUser) diff --git a/services/managers/eve_api_manager.py b/services/managers/eve_api_manager.py index bff85c7e..e6702982 100644 --- a/services/managers/eve_api_manager.py +++ b/services/managers/eve_api_manager.py @@ -16,14 +16,10 @@ class EveApiManager(): def get_characters_from_api(api_id, api_key): chars = [] logger.debug("Getting characters from api id %s" % api_id) - try: - api = evelink.api.API(api_key=(api_id, api_key)) - # Should get characters - account = evelink.account.Account(api=api) - chars = account.characters() - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") - + api = evelink.api.API(api_key=(api_id, api_key)) + # Should get characters + account = evelink.account.Account(api=api) + chars = account.characters() logger.debug("Retrieved characters %s from api id %s" % (chars, api_id)) return chars @@ -31,15 +27,11 @@ class EveApiManager(): def get_corporation_ticker_from_id(corp_id): logger.debug("Getting ticker for corp id %s" % corp_id) ticker = "" - try: - api = evelink.api.API() - corp = evelink.corp.Corp(api) - response = corp.corporation_sheet(corp_id) - logger.debug("Retrieved corp sheet for id %s: %s" % (corp_id, response)) - ticker = response[0]['ticker'] - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") - + api = evelink.api.API() + corp = evelink.corp.Corp(api) + response = corp.corporation_sheet(corp_id) + logger.debug("Retrieved corp sheet for id %s: %s" % (corp_id, response)) + ticker = response[0]['ticker'] logger.debug("Determined corp id %s ticker: %s" % (corp_id, ticker)) return ticker @@ -47,13 +39,10 @@ class EveApiManager(): def get_alliance_information(alliance_id): results = {} logger.debug("Getting info for alliance with id %s" % alliance_id) - try: - api = evelink.api.API() - eve = evelink.eve.EVE(api=api) - alliance = eve.alliances() - results = alliance[0][int(alliance_id)] - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") + api = evelink.api.API() + eve = evelink.eve.EVE(api=api) + alliance = eve.alliances() + results = alliance[0][int(alliance_id)] logger.debug("Got alliance info %s" % results) return results @@ -61,88 +50,57 @@ class EveApiManager(): def get_corporation_information(corp_id): logger.debug("Getting info for corp with id %s" % corp_id) results = {} - try: - api = evelink.api.API() - corp = evelink.corp.Corp(api=api) - corpinfo = corp.corporation_sheet(corp_id=int(corp_id)) - results = corpinfo[0] - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") + api = evelink.api.API() + corp = evelink.corp.Corp(api=api) + corpinfo = corp.corporation_sheet(corp_id=int(corp_id)) + results = corpinfo[0] logger.debug("Got corp info %s" % results) return results @staticmethod def check_api_is_type_account(api_id, api_key): logger.debug("Checking if api id %s is account." % api_id) - try: - api = evelink.api.API(api_key=(api_id, api_key)) - account = evelink.account.Account(api=api) - info = account.key_info() - logger.debug("API id %s is type %s" % (api_id, info[0]['type'])) - return info[0]['type'] == "account" - - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") - return None - + api = evelink.api.API(api_key=(api_id, api_key)) + account = evelink.account.Account(api=api) + info = account.key_info() + logger.debug("API id %s is type %s" % (api_id, info[0]['type'])) + return info[0]['type'] == "account" @staticmethod def check_api_is_full(api_id, api_key): logger.debug("Checking if api id %s meets member requirements." % api_id) - try: - api = evelink.api.API(api_key=(api_id, api_key)) - account = evelink.account.Account(api=api) - info = account.key_info() - logger.debug("API has mask %s, required is %s" % (info[0]['access_mask'], settings.MEMBER_API_MASK)) - return info[0]['access_mask'] & int(settings.MEMBER_API_MASK) == int(settings.MEMBER_API_MASK) - - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") - return None + api = evelink.api.API(api_key=(api_id, api_key)) + account = evelink.account.Account(api=api) + info = account.key_info() + logger.debug("API has mask %s, required is %s" % (info[0]['access_mask'], settings.MEMBER_API_MASK)) + return info[0]['access_mask'] & int(settings.MEMBER_API_MASK) == int(settings.MEMBER_API_MASK) @staticmethod def check_blue_api_is_full(api_id, api_key): logger.debug("Checking if api id %s meets blue requirements." % api_id) - try: - api = evelink.api.API(api_key=(api_id, api_key)) - account = evelink.account.Account(api=api) - info = account.key_info() - logger.debug("API has mask %s, required is %s" % (info[0]['access_mask'], settings.BLUE_API_MASK)) - return info[0]['access_mask'] & int(settings.BLUE_API_MASK) == int(settings.BLUE_API_MASK) + api = evelink.api.API(api_key=(api_id, api_key)) + account = evelink.account.Account(api=api) + info = account.key_info() + logger.debug("API has mask %s, required is %s" % (info[0]['access_mask'], settings.BLUE_API_MASK)) + return info[0]['access_mask'] & int(settings.BLUE_API_MASK) == int(settings.BLUE_API_MASK) - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") - return None - - @staticmethod def get_api_info(api_id, api_key): logger.debug("Getting api info for key id %s" % api_id) - try: - api = evelink.api.API(api_key=(api_id, api_key)) - account = evelink.account.Account(api=api) - info = account.key_info() - logger.debug("Got info for api id %s: %s" % (api_id, info)) - return info - - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.") - return None + api = evelink.api.API(api_key=(api_id, api_key)) + account = evelink.account.Account(api=api) + info = account.key_info() + logger.debug("Got info for api id %s: %s" % (api_id, info)) + return info @staticmethod def api_key_is_valid(api_id, api_key): logger.debug("Checking if api id %s is valid." % api_id) - try: - api = evelink.api.API(api_key=(api_id, api_key)) - account = evelink.account.Account(api=api) - info = account.key_info() - logger.info("Verified api id %s is still valid." % api_id) - return True - except evelink.api.APIError as error: - logger.exception("APIError occured while validating api id %s" % api_id) - - logger.info("API id %s is invalid." % api_id) - return False + api = evelink.api.API(api_key=(api_id, api_key)) + account = evelink.account.Account(api=api) + info = account.key_info() + logger.info("Verified api id %s is still valid." % api_id) + return True @staticmethod def check_if_api_server_online(): @@ -170,6 +128,9 @@ class EveApiManager(): logger.debug("Confirmed id %s is a corp." % corp_id) return True except evelink.api.APIError as error: + if int(error.code) == '523': + logger.debug("Confirmed id %s is not a corp" % corp_id) + return False 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) @@ -178,16 +139,13 @@ class EveApiManager(): @staticmethod def get_corp_standings(): if settings.CORP_API_ID and settings.CORP_API_VCODE: - try: - logger.debug("Getting corp standings with api id %s" % settings.CORP_API_ID) - api = evelink.api.API(api_key=(settings.CORP_API_ID, settings.CORP_API_VCODE)) - corp = evelink.corp.Corp(api=api) - corpinfo = corp.contacts() - results = corpinfo.result - logger.debug("Got corp standings from settings: %s" % results) - return results - except evelink.api.APIError as error: - logger.exception("Unhandled APIError occured.", exc_info=True) + logger.debug("Getting corp standings with api id %s" % settings.CORP_API_ID) + api = evelink.api.API(api_key=(settings.CORP_API_ID, settings.CORP_API_VCODE)) + corp = evelink.corp.Corp(api=api) + corpinfo = corp.contacts() + results = corpinfo.result + logger.debug("Got corp standings from settings: %s" % results) + return results else: logger.error("No corp API key supplied in settings. Unable to get standings.") return {} diff --git a/services/managers/mumble_manager.py b/services/managers/mumble_manager.py index c312e00e..e70f56ac 100755 --- a/services/managers/mumble_manager.py +++ b/services/managers/mumble_manager.py @@ -6,46 +6,13 @@ import django from django.db import connections from django.conf import settings +from services.models import MumbleUser + import logging logger = logging.getLogger(__name__) class MumbleManager: - SQL_SELECT_USER_MAX_ID = r"SELECT max(user_id)+1 as next_id from murmur_users" - - SQL_SELECT_GROUP_MAX_ID = r"SELECT MAX(group_id)+1 FROM murmur_groups" - - SQL_CREATE_USER = r"INSERT INTO murmur_users (server_id, user_id, name, pw) VALUES (%s, %s, %s, %s)" - - SQL_SELECT_GET_USER_ID_BY_NAME = r"SELECT user_id from murmur_users WHERE name = %s AND server_id = %s" - - SQL_CHECK_USER_EXIST = r"SELECT name from murmur_users WHERE name = %s AND server_id = %s" - - SQL_DELETE_USER = r"DELETE FROM murmur_users WHERE name = %s AND server_id = %s" - - SQL_UPDATE_USER_PASSWORD = r"UPDATE murmur_users SET pw = %s WHERE name = %s AND server_id = %s" - - SQL_GET_GROUPS = r"SELECT group_id, name FROM murmur_groups WHERE server_id = %s AND channel_id = 0" - - SQL_GET_GROUP_FROM_NAME = r"SELECT group_id, name FROM murmur_groups " \ - r"WHERE server_id = %s AND channel_id = 0 AND name = %s" - - SQL_GET_USER_GROUPS = r"SELECT murmur_groups.name FROM murmur_groups, murmur_group_members WHERE " \ - r"murmur_group_members.group_id = murmur_groups.group_id AND " \ - r"murmur_group_members.server_id = murmur_groups.server_id AND " \ - r"murmur_group_members.user_id = %s" - - SQL_ADD_GROUP = r"INSERT INTO murmur_groups (group_id, server_id, name, channel_id, inherit, inheritable) " \ - r"VALUES (%s, %s, %s, 0, 1, 1)" - - SQL_ADD_USER_TO_GROUP = r"INSERT INTO murmur_group_members (group_id, server_id, user_id, addit) " \ - r"VALUES (%s, %s, %s, 1)" - - SQL_DELETE_USER_FROM_GROUP = r"DELETE FROM murmur_group_members WHERE group_id = %s " \ - r"AND server_id = %s AND user_id = %s" - - def __init__(self): - pass @staticmethod def __santatize_username(username): @@ -69,192 +36,81 @@ class MumbleManager: def _gen_pwhash(password): return hashlib.sha1(password).hexdigest() - @staticmethod - def _get_groups(): - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_GET_GROUPS, [settings.MUMBLE_SERVER_ID]) - rows = dbcursor.fetchall() - - out = {} - for row in rows: - out[row[1]] = row[0] - - logger.debug("Got mumble groups %s" % out) - return out - - @staticmethod - def _get_group(name): - logger.debug("Looking for group name %s in mumble." % name) - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_GET_GROUP_FROM_NAME, [settings.MUMBLE_SERVER_ID, name]) - row = dbcursor.fetchone() - if row: - logger.debug("Found group %s in mumble - %s" % (name, row[0])) - return row[0] - - @staticmethod - def _get_user_groups(name): - logger.debug("Getting mumble groups for username %s" % name) - dbcursor = connections['mumble'].cursor() - user_id = MumbleManager.get_user_id_by_name(name) - dbcursor.execute(MumbleManager.SQL_GET_USER_GROUPS, [user_id]) - out = [row[0] for row in dbcursor.fetchall()] - logger.debug("Got user %s mumble groups %s" % (name, out)) - return out - - @staticmethod - def _add_group(name): - logger.debug("Adding group %s to mumble server." % name) - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_SELECT_GROUP_MAX_ID) - row = dbcursor.fetchone() - groupid = row[0] - dbcursor.execute(MumbleManager.SQL_ADD_GROUP, [groupid, settings.MUMBLE_SERVER_ID, name]) - logger.info("Created group %s on mumble server with id %s" % (name, groupid)) - return groupid - - @staticmethod - def _add_user_to_group(userid, groupid): - if userid != None: - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_ADD_USER_TO_GROUP, [groupid, settings.MUMBLE_SERVER_ID, userid]) - logger.info("Added user id %s to mumble group id %s" % (userid, groupid)) - - @staticmethod - def _del_user_from_group(userid, groupid): - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_DELETE_USER_FROM_GROUP, [groupid, settings.MUMBLE_SERVER_ID, userid]) - logger.info("Removed user id %s from mumble group id %s" % (userid, groupid)) - - @staticmethod - def get_user_id_by_name(name): - logger.debug("Getting mumble user id for user with name %s" % name) - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_SELECT_GET_USER_ID_BY_NAME, [name, settings.MUMBLE_SERVER_ID]) - row = dbcursor.fetchone() - if row: - logger.debug("Got mumble user id %s for name %s" % (row[0], name)) - return row[0] - @staticmethod def create_user(corp_ticker, username): logger.debug("Creating mumble user with username %s and ticker %s" % (username, corp_ticker)) - dbcursor = connections['mumble'].cursor() username_clean = MumbleManager.__santatize_username(MumbleManager.__generate_username(username, corp_ticker)) password = MumbleManager.__generate_random_pass() pwhash = MumbleManager._gen_pwhash(password) logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % (username_clean, pwhash[0:5])) - try: - dbcursor.execute(MumbleManager.SQL_SELECT_USER_MAX_ID) - user_id = dbcursor.fetchone()[0] - - dbcursor.execute(MumbleManager.SQL_CREATE_USER, - [settings.MUMBLE_SERVER_ID, user_id, username_clean, pwhash]) - logger.info("Added user to mumble with username %s" % username_clean) + if MumbleUser.objects.filter(username=username_clean).exists() is False: + logger.info("Creating mumble user %s" % username_clean) + model = MumbleUser.objects.create(username=username_clean, pwhash=pwhash) + return username_clean, password + else: + logger.warn("Mumble user %s already exists. Updating password") + model = MumbleUser.objects.get(username=username_clean) + model.pwhash = pwhash + model.save() + logger.info("Updated mumble user %s" % username_clean) return username_clean, password - except django.db.utils.IntegrityError as error: - logger.exception("IntegrityError during mumble create_user occured.") - except: - logger.exception("Unhandled exception occured.") - logger.error("Exception prevented creation of mumble user. Returning blank for username, password.") - return "", "" @staticmethod def create_blue_user(corp_ticker, username): logger.debug("Creating mumble blue user with username %s and ticker %s" % (username, corp_ticker)) - dbcursor = connections['mumble'].cursor() - username_clean = MumbleManager.__santatize_username(MumbleManager.__generate_username_blue(username, - corp_ticker)) + username_clean = MumbleManager.__santatize_username(MumbleManager.__generate_username_blue(username, corp_ticker)) password = MumbleManager.__generate_random_pass() pwhash = MumbleManager._gen_pwhash(password) logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % (username_clean, pwhash[0:5])) - try: - dbcursor.execute(MumbleManager.SQL_SELECT_USER_MAX_ID) - user_id = dbcursor.fetchone()[0] - - dbcursor.execute(MumbleManager.SQL_CREATE_USER, - [settings.MUMBLE_SERVER_ID, user_id, username_clean, pwhash]) - logger.info("Added blue user to mumble with username %s" % username_clean) + if MumbleUser.objects.filter(username=username_clean).exists() is False: + logger.info("Creating mumble user %s" % username_clean) + model = MumbleUser.objects.create(username=username_clean, pwhash=pwhash) + return username_clean, password + else: + logger.warn("Mumble user %s already exists. Updating password") + model = MumbleUser.objects.get(username=username_clean) + model.pwhash = pwhash + model.save() + logger.info("Updated mumble user %s" % username_clean) return username_clean, password - except: - logger.exception("Unhandled exception occured.") - logger.error("Exception prevented creation of mumble blue user. Returning blank for username, password.") - return "", "" - - @staticmethod - def check_user_exist(username): - logger.debug("Checking if username %s exists on mumble." % username) - dbcursor = connections['mumble'].cursor() - dbcursor.execute(MumbleManager.SQL_CHECK_USER_EXIST, - [username, settings.MUMBLE_SERVER_ID]) - - row = dbcursor.fetchone() - if row and row[0].lower() == username.lower(): - logger.debug("Found username %s on mumble." % username) - return True - logger.debug("Unable to find username %s on mumble." % username) - return False @staticmethod def delete_user(username): logger.debug("Deleting user %s from mumble." % username) - dbcursor = connections['mumble'].cursor() - if MumbleManager.check_user_exist(username): - try: - - dbcursor.execute(MumbleManager.SQL_DELETE_USER, - [username, settings.MUMBLE_SERVER_ID]) - logger.info("Deleted user %s from mumble." % username) - return True - except: - logger.exception("Exception prevented deletion of user %s from mumble." % username) - return False - logger.error("User %s not found on mumble. Unable to delete." % username) + if MumbleUser.objects.filter(username=username).exists(): + MumbleUser.objects.filter(username=username).delete() + logger.info("Deleted user %s from mumble" % username) + return True + logger.error("Unable to delete user %s from mumble: MumbleUser model not found" % username) return False @staticmethod def update_user_password(username, password=None): logger.debug("Updating mumble user %s password." % username) - dbcursor = connections['mumble'].cursor() if not password: password = MumbleManager.__generate_random_pass() pwhash = MumbleManager._gen_pwhash(password) logger.debug("Proceeding with mumble user %s password update - pwhash starts with %s" % (username, pwhash[0:5])) - if MumbleManager.check_user_exist(username): - try: - - dbcursor.execute(MumbleManager.SQL_UPDATE_USER_PASSWORD, - [pwhash, username, settings.MUMBLE_SERVER_ID]) - logger.info("Updated mumble user %s password." % username) - return password - except: - logger.exception("Exception prevented updating of mumble user %s password." % username) - return "" + if MumbleUser.objects.filter(username=username).exists(): + model = MumbleUser.objects.get(username=username) + model.pwhash = pwhash + model.save() + return password logger.error("User %s not found on mumble. Unable to update password." % username) return "" @staticmethod def update_groups(username, groups): logger.debug("Updating mumble user %s groups %s" % (username, groups)) - userid = MumbleManager.get_user_id_by_name(username) - mumble_groups = MumbleManager._get_groups() - user_groups = set(MumbleManager._get_user_groups(username)) - act_groups = set([g.replace(' ', '-') for g in groups]) - addgroups = act_groups - user_groups - remgroups = user_groups - act_groups - logger.info("Updating mumble user %s groups - adding %s, removing %s" % (username, addgroups, remgroups)) - for g in addgroups: - if not g in mumble_groups: - mumble_groups[g] = MumbleManager._add_group(g) - try: - logger.debug("Adding mumble user %s to group %s" % (userid, mumble_groups[g])) - MumbleManager._add_user_to_group(userid, mumble_groups[g]) - except: - logger.exception("Exception occured while adding mumble user %s with id %s to group %s with id %s" % (username, userid, g, mumble_groups[g])) - - for g in remgroups: - try: - logger.debug("Deleting mumble user %s from group %s" % (userid, mumble_groups[g])) - MumbleManager._del_user_from_group(userid, mumble_groups[g]) - except: - logger.exception("Exception occured while removing mumble user %s with id %s from group %s with id %s" % (username, userid, g, mumble_groups[g])) + safe_groups = list(set([g.replace(' ', '-') for g in groups])) + groups ='' + for g in safe_groups: + groups = groups + g + ',' + groups = groups.strip(',') + if MumbleUser.objects.filter(username=username).exists(): + logger.info("Updating mumble user %s groups to %s" % (username, safe_groups)) + model = MumbleUser.objects.get(username=username) + model.groups = groups + model.save() + else: + logger.error("User %s not found on mumble. Unable to update groups." % username) diff --git a/services/models.py b/services/models.py index 2cc7f017..7a69db70 100644 --- a/services/models.py +++ b/services/models.py @@ -38,3 +38,11 @@ class DiscordAuthToken(models.Model): def __str__(self): output = "Discord Token for email %s user %s" % (self.email, self.user) return output.encode('utf-8') + +class MumbleUser(models.Model): + username = models.CharField(max_length=254, unique=True) + pwhash = models.CharField(max_length=40) + groups = models.TextField(blank=True, null=True) + + def __str__(self): + return self.username diff --git a/services/tasks.py b/services/tasks.py index 60a30bd3..e3a45694 100644 --- a/services/tasks.py +++ b/services/tasks.py @@ -6,6 +6,7 @@ from services.models import UserTSgroup from services.models import AuthTS from services.models import TSgroup from services.models import DiscordAuthToken +from services.models import MumbleUser logger = logging.getLogger(__name__) @@ -81,6 +82,8 @@ def disable_mumble(): auth.save() logger.info("Deleting all SyncGroupCache models for mumble") SyncGroupCache.objects.filter(servicename="mumble").delete() + logger.info("Deleting all MumbleUser models") + MumbleUser.objects.all().delete() def disable_ipboard(): if settings.ENABLE_AUTH_IPBOARD: diff --git a/services/views.py b/services/views.py index ab08dbd8..33535a26 100755 --- a/services/views.py +++ b/services/views.py @@ -16,7 +16,6 @@ from managers.teamspeak3_manager import Teamspeak3Manager from managers.discord_manager import DiscordManager from authentication.managers import AuthServicesInfoManager from eveonline.managers import EveManager -from celerytask.tasks import remove_all_syncgroups_for_service from celerytask.tasks import update_jabber_groups from celerytask.tasks import update_mumble_groups from celerytask.tasks import update_forum_groups @@ -135,7 +134,7 @@ def activate_forum(request): if result[0] != "": AuthServicesInfoManager.update_user_forum_info(result[0], result[1], request.user) logger.debug("Updated authserviceinfo for user %s with forum credentials. Updating groups." % request.user) - update_forum_groups(request.user) + update_forum_groups.delay(request.user) logger.info("Succesfully activated forum for user %s" % request.user) return HttpResponseRedirect("/services/") logger.error("Unsuccesful attempt to activate forum for user %s" % request.user) @@ -148,7 +147,6 @@ def deactivate_forum(request): logger.debug("deactivate_forum called by user %s" % request.user) authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = Phpbb3Manager.disable_user(authinfo.forum_username) - remove_all_syncgroups_for_service(request.user, "phpbb") # false we failed if result: AuthServicesInfoManager.update_user_forum_info("", "", request.user) @@ -185,7 +183,7 @@ def activate_ipboard_forum(request): if result[0] != "": AuthServicesInfoManager.update_user_ipboard_info(result[0], result[1], request.user) logger.debug("Updated authserviceinfo for user %s with ipboard credentials. Updating groups." % request.user) - update_ipboard_groups(request.user) + update_ipboard_groups.delay(request.user) logger.info("Succesfully activated ipboard for user %s" % request.user) return HttpResponseRedirect("/services/") logger.error("Unsuccesful attempt to activate ipboard for user %s" % request.user) @@ -198,7 +196,6 @@ def deactivate_ipboard_forum(request): logger.debug("deactivate_ipboard_forum called by user %s" % request.user) authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = IPBoardManager.disable_user(authinfo.ipboard_username) - remove_all_syncgroups_for_service(request.user, "ipboard") # false we failed if result: AuthServicesInfoManager.update_user_ipboard_info("", "", request.user) @@ -234,7 +231,7 @@ def activate_jabber(request): if info[0] is not "": AuthServicesInfoManager.update_user_jabber_info(info[0], info[1], request.user) logger.debug("Updated authserviceinfo for user %s with jabber credentials. Updating groups." % request.user) - update_jabber_groups(request.user) + update_jabber_groups.delay(request.user) logger.info("Succesfully activated jabber for user %s" % request.user) return HttpResponseRedirect("/services/") logger.error("Unsuccesful attempt to activate jabber for user %s" % request.user) @@ -247,7 +244,6 @@ def deactivate_jabber(request): logger.debug("deactivate_jabber called by user %s" % request.user) authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = OpenfireManager.delete_user(authinfo.jabber_username) - remove_all_syncgroups_for_service(request.user, "openfire") # If our username is blank means we failed if result: AuthServicesInfoManager.update_user_jabber_info("", "", request.user) @@ -288,7 +284,7 @@ def activate_mumble(request): if result[0] is not "": AuthServicesInfoManager.update_user_mumble_info(result[0], result[1], request.user) logger.debug("Updated authserviceinfo for user %s with mumble credentials. Updating groups." % request.user) - update_mumble_groups(request.user) + update_mumble_groups.delay(request.user) logger.info("Succesfully activated mumble for user %s" % request.user) return HttpResponseRedirect("/services/") logger.error("Unsuccessful attempt to activate mumble for user %s" % request.user) @@ -301,7 +297,6 @@ def deactivate_mumble(request): logger.debug("deactivate_mumble called by user %s" % request.user) authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = MumbleManager.delete_user(authinfo.mumble_username) - remove_all_syncgroups_for_service(request.user, "mumble") # if false we failed if result: AuthServicesInfoManager.update_user_mumble_info("", "", request.user) @@ -344,7 +339,7 @@ def activate_teamspeak3(request): if result[0] is not "": AuthServicesInfoManager.update_user_teamspeak3_info(result[0], result[1], request.user) logger.debug("Updated authserviceinfo for user %s with TS3 credentials. Updating groups." % request.user) - update_teamspeak3_groups(request.user) + update_teamspeak3_groups.delay(request.user) logger.info("Succesfully activated TS3 for user %s" % request.user) return HttpResponseRedirect("/services/") logger.error("Unsuccessful attempt to activate TS3 for user %s" % request.user) @@ -358,8 +353,6 @@ def deactivate_teamspeak3(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) - remove_all_syncgroups_for_service(request.user, "teamspeak3") - # if false we failed if result: AuthServicesInfoManager.update_user_teamspeak3_info("", "", request.user) @@ -378,8 +371,6 @@ def reset_teamspeak3_perm(request): logger.debug("Deleting TS3 user for user %s" % request.user) Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) - remove_all_syncgroups_for_service(request.user, "teamspeak3") - if check_if_user_has_permission(request.user, "blue_member"): logger.debug("Generating new permission key for blue user %s with main character %s" % (request.user, character)) result = Teamspeak3Manager.generate_new_blue_permissionkey(authinfo.teamspeak3_uid, character.character_name, @@ -393,7 +384,7 @@ def reset_teamspeak3_perm(request): if result != "": AuthServicesInfoManager.update_user_teamspeak3_info(result[0], result[1], request.user) logger.debug("Updated authserviceinfo for user %s with TS3 credentials. Updating groups." % request.user) - update_teamspeak3_groups(request.user) + update_teamspeak3_groups.delay(request.user) logger.info("Successfully reset TS3 permission key for user %s" % request.user) return HttpResponseRedirect("/services/") logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user) @@ -413,7 +404,6 @@ def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = DiscordManager.delete_user(authinfo.discord_uid) if result: - remove_all_syncgroups_for_service(request.user, "discord") AuthServicesInfoManager.update_user_discord_info("", request.user) logger.info("Succesfully deactivated discord for user %s" % request.user) return HttpResponseRedirect("/services/") @@ -453,7 +443,7 @@ def activate_discord(request): if user_id != "": AuthServicesInfoManager.update_user_discord_info(user_id, request.user) logger.debug("Updated discord id %s for user %s" % (user_id, request.user)) - update_discord_groups(request.user) + update_discord_groups.delay(request.user) logger.debug("Updated discord groups for user %s." % request.user) success = True logger.info("Succesfully activated discord for user %s" % request.user) @@ -592,4 +582,3 @@ def set_ipboard_password(request): logger.debug("Rendering form for user %s" % request.user) context = {'form': form, 'service': 'IPBoard', 'error': error} return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) - diff --git a/stock/templates/registered/hrapplicationcorpchoice.html b/stock/templates/registered/hrapplicationcorpchoice.html new file mode 100644 index 00000000..0ffeabc4 --- /dev/null +++ b/stock/templates/registered/hrapplicationcorpchoice.html @@ -0,0 +1,25 @@ +{% extends "public/base.html" %} +{% load staticfiles %} +{% block title %}Choose a Corp{% endblock %} +{% block page_title %}Choose a Corp{% endblock page_title %} +{% block content %} +
+ {{ choice.1 }} + | +
Username | -Main Character | Corporation | Status | Actions | @@ -32,15 +29,14 @@ {% for personal_app in personal_apps %}|||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
{{ personal_app.user.username }} | -{{ personal_app.character_name }} | -{{ personal_app.corp.corporation_name }} | +{{ personal_app.form.corp.corporation_name }} |
- {% if personal_app.approved_denied == None %}
- Pending
- {% elif personal_app.approved_denied == True %}
- Approved
+ {% if personal_app.approved == None %}
+ Pending
+ {% elif personal_app.approved == True %}
+ Approved
{% else %}
- Rejected
+ Rejected
{% endif %}
|
@@ -69,40 +65,93 @@
-
-
diff --git a/stock/templates/registered/hrapplicationsearchview.html b/stock/templates/registered/hrapplicationsearchview.html
index 15e5098c..d4e7821f 100755
--- a/stock/templates/registered/hrapplicationsearchview.html
+++ b/stock/templates/registered/hrapplicationsearchview.html
@@ -31,16 +31,16 @@
{% for app in applications %}
+
{% endif %}
+
+
+
+
+
+
+
| ||||||||||||||||||||||||||||||||||||
{{ app.id }} | -{{ app.user.username }} | -{{ app.character_name }} | -{{ app.corp.corporation_name }} | +{{ app.user }} | +{{ app.main_character }} | +{{ app.form.corp }} |
- {% if app.approved_denied == None %}
- Pending
- {% elif app.approved_denied == True %}
- Approved
+ {% if app.approved == None %}
+ Pending
+ {% elif app.approved == True %}
+ Approved
{% else %}
- Rejected
+ Rejected
{% endif %}
|
diff --git a/stock/templates/registered/hrapplicationview.html b/stock/templates/registered/hrapplicationview.html
old mode 100755
new mode 100644
index 55b55c55..5823ed11
--- a/stock/templates/registered/hrapplicationview.html
+++ b/stock/templates/registered/hrapplicationview.html
@@ -1,223 +1,153 @@
{% extends "public/base.html" %}
-{% load bootstrap %}
{% load staticfiles %}
-
+{% load bootstrap %}
{% block title %}Alliance Auth - View Application{% endblock %}
-
{% block page_title %}View Application{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block content %}
View Application-
-
-
+ {% if app.approved %}
+
-
+ Approved
+ {% elif app.approved == False %}
+ Denied
+ {% else %}
+ Pending
+ {% endif %}
+ {% if app.reviewer_str %}
+ Reviewer: {{ app.reviewer_str }}
+ {% endif %}
+
+
+
+ Applicant
+
+
+ Characters
+
+ {% for response in responses %}
+
+ {% if buttons %}
+
+
+ {% endfor %}
+ {{ response.question.title }}
+ {{ response.answer }}
+
+ {% if perms.auth.human_resources %}
+
+ {% endif %}
+
+ Actions
+ {% if app.approved == None %}
+ {% if app.reviewer == user %}
+ {% if perms.hrapplications.approve_application %}
+ Approve
+ {% endif %}
+ {% if perms.hrapplications.reject_application %}
+ Reject
+ {% endif %}
+ {% if perms.hrapplications.delete_application %}
+ Delete
+ {% endif %}
+ {% elif not app.reviewer %}
+ Mark in Progress
+ {% endif %}
+ {% endif %}
+ {% if perms.hrapplications.add_applicationcomment %}
+
+ {% endif %}
+ {% if perms.hrapplications.view_apis %}
+ {% for api in apis %}
+ API {{ api.api_id }}
+ {% endfor %}
+ {% endif %}
+
+
+ {% endif %}
+
+
+
+
+
+
+ {% for comment in comments %}
+
+
+
+ {% endfor %}
+
+
+ {{comment.created}} - {{ comment.user }}
+ {{ comment.text }}
+ |