Deactivate services when user loses main character.

This will prevent issues with service username formatting when access permissions are granted to the guest state. While users without mains cannot activate a service they could still retain an active account and it's possible to schedule a nickname update task which would subsequently error out.

Also it seems like a security issue if someone has a service account but their EVE character isn't known. cc8a7a18d23e9beb6e0a498a314e4c3bcae3f700 prevented accessing the services page without a main, now this ensures users don't have an account to manage.
This commit is contained in:
Adarnof 2018-04-20 13:28:41 -04:00
parent b65ccac58f
commit e47c04a0b0
3 changed files with 31 additions and 4 deletions

View File

@ -141,7 +141,7 @@ def pre_delete_user(sender, instance, *args, **kwargs):
@receiver(pre_save, sender=User) @receiver(pre_save, sender=User)
def pre_save_user(sender, instance, *args, **kwargs): def disable_services_on_inactive(sender, instance, *args, **kwargs):
logger.debug("Received pre_save from %s" % instance) logger.debug("Received pre_save from %s" % instance)
# check if user is being marked active/inactive # check if user is being marked active/inactive
if not instance.pk: if not instance.pk:
@ -154,3 +154,17 @@ def pre_save_user(sender, instance, *args, **kwargs):
disable_user(instance) disable_user(instance)
except User.DoesNotExist: except User.DoesNotExist:
pass pass
@receiver(pre_save, sender=UserProfile)
def disable_services_on_no_main(sender, instance, *args, **kwargs):
if not instance.pk:
# new model being created
return
try:
old_instance = UserProfile.objects.get(pk=instance.pk)
if old_instance.main_character and not instance.main_character:
logger.info("Disabling services due to loss of main character for user {0}".format(instance.user))
disable_user(instance.user)
except UserProfile.DoesNotExist:
pass

View File

@ -9,6 +9,7 @@ from allianceauth.authentication.models import State
class ServicesSignalsTestCase(TestCase): class ServicesSignalsTestCase(TestCase):
def setUp(self): def setUp(self):
self.member = AuthUtils.create_user('auth_member', disconnect_signals=True) self.member = AuthUtils.create_user('auth_member', disconnect_signals=True)
AuthUtils.add_main_character(self.member, 'Test', '1', '2', 'Test Corp', 'TEST')
self.none_user = AuthUtils.create_user('none_user', disconnect_signals=True) self.none_user = AuthUtils.create_user('none_user', disconnect_signals=True)
@mock.patch('allianceauth.services.signals.transaction') @mock.patch('allianceauth.services.signals.transaction')
@ -67,6 +68,18 @@ class ServicesSignalsTestCase(TestCase):
args, kwargs = disable_user.call_args args, kwargs = disable_user.call_args
self.assertEqual(self.member, args[0]) self.assertEqual(self.member, args[0])
@mock.patch('allianceauth.services.signals.disable_user')
def test_disable_services_on_loss_of_main_character(self, disable_user):
"""
Test a user set inactive has disable_member called
"""
self.member.profile.main_character = None
self.member.profile.save() # Signal Trigger
self.assertTrue(disable_user.called)
args, kwargs = disable_user.call_args
self.assertEqual(self.member, args[0])
@mock.patch('allianceauth.services.signals.transaction') @mock.patch('allianceauth.services.signals.transaction')
@mock.patch('allianceauth.services.signals.ServicesHook') @mock.patch('allianceauth.services.signals.ServicesHook')
def test_m2m_changed_group_permissions(self, services_hook, transaction): def test_m2m_changed_group_permissions(self, services_hook, transaction):

View File

@ -9,7 +9,7 @@ from allianceauth.eveonline.models import EveCharacter
from allianceauth.services.signals import m2m_changed_group_permissions, m2m_changed_user_permissions, \ from allianceauth.services.signals import m2m_changed_group_permissions, m2m_changed_user_permissions, \
m2m_changed_state_permissions m2m_changed_state_permissions
from allianceauth.services.signals import m2m_changed_user_groups, pre_save_user from allianceauth.services.signals import m2m_changed_user_groups, disable_services_on_inactive
class AuthUtils: class AuthUtils:
@ -90,7 +90,7 @@ class AuthUtils:
m2m_changed.disconnect(m2m_changed_group_permissions, sender=Group.permissions.through) m2m_changed.disconnect(m2m_changed_group_permissions, sender=Group.permissions.through)
m2m_changed.disconnect(m2m_changed_user_permissions, sender=User.user_permissions.through) m2m_changed.disconnect(m2m_changed_user_permissions, sender=User.user_permissions.through)
m2m_changed.disconnect(m2m_changed_state_permissions, sender=State.permissions.through) m2m_changed.disconnect(m2m_changed_state_permissions, sender=State.permissions.through)
pre_save.disconnect(pre_save_user, sender=User) pre_save.disconnect(disable_services_on_inactive, sender=User)
m2m_changed.disconnect(state_member_corporations_changed, sender=State.member_corporations.through) m2m_changed.disconnect(state_member_corporations_changed, sender=State.member_corporations.through)
m2m_changed.disconnect(state_member_characters_changed, sender=State.member_characters.through) m2m_changed.disconnect(state_member_characters_changed, sender=State.member_characters.through)
m2m_changed.disconnect(state_member_alliances_changed, sender=State.member_alliances.through) m2m_changed.disconnect(state_member_alliances_changed, sender=State.member_alliances.through)
@ -102,7 +102,7 @@ class AuthUtils:
m2m_changed.connect(m2m_changed_group_permissions, sender=Group.permissions.through) m2m_changed.connect(m2m_changed_group_permissions, sender=Group.permissions.through)
m2m_changed.connect(m2m_changed_user_permissions, sender=User.user_permissions.through) m2m_changed.connect(m2m_changed_user_permissions, sender=User.user_permissions.through)
m2m_changed.connect(m2m_changed_state_permissions, sender=State.permissions.through) m2m_changed.connect(m2m_changed_state_permissions, sender=State.permissions.through)
pre_save.connect(pre_save_user, sender=User) pre_save.connect(disable_services_on_inactive, sender=User)
m2m_changed.connect(state_member_corporations_changed, sender=State.member_corporations.through) m2m_changed.connect(state_member_corporations_changed, sender=State.member_corporations.through)
m2m_changed.connect(state_member_characters_changed, sender=State.member_characters.through) m2m_changed.connect(state_member_characters_changed, sender=State.member_characters.through)
m2m_changed.connect(state_member_alliances_changed, sender=State.member_alliances.through) m2m_changed.connect(state_member_alliances_changed, sender=State.member_alliances.through)