mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-14 19:16:23 +01:00
[v2] Alliance and Corp Autogroups (#902)
* Add pseudo foreign keys to EveCharacter model * Ensure populate alliance is called on create * Add unit tests for model * Add extra signal for state removal/addition * Add unit tests for signals * Add tests for manager * Add migrations * Add sync command to admin control * Prevent whitespace being stripped from group names * Add documentation
This commit is contained in:
1
allianceauth/eveonline/autogroups/__init__.py
Normal file
1
allianceauth/eveonline/autogroups/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
default_app_config = 'allianceauth.eveonline.autogroups.apps.EveAutogroupsConfig'
|
||||
39
allianceauth/eveonline/autogroups/admin.py
Normal file
39
allianceauth/eveonline/autogroups/admin.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from django.contrib import admin
|
||||
from django.db import models
|
||||
from .models import AutogroupsConfig
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def sync_user_groups(modeladmin, request, queryset):
|
||||
for agc in queryset:
|
||||
logger.debug("update_all_states_group_membership for {}".format(agc))
|
||||
agc.update_all_states_group_membership()
|
||||
|
||||
|
||||
class AutogroupsConfigAdmin(admin.ModelAdmin):
|
||||
formfield_overrides = {
|
||||
models.CharField: {'strip': False}
|
||||
}
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj: # This is the case when obj is already created i.e. it's an edit
|
||||
return [
|
||||
'corp_group_prefix', 'corp_name_source', 'alliance_group_prefix', 'alliance_name_source',
|
||||
'replace_spaces', 'replace_spaces_with'
|
||||
]
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_actions(self, request):
|
||||
actions = super(AutogroupsConfigAdmin, self).get_actions(request)
|
||||
actions['sync_user_groups'] = (sync_user_groups,
|
||||
'sync_user_groups',
|
||||
'Sync all users groups for this Autogroup Config')
|
||||
return actions
|
||||
|
||||
|
||||
admin.site.register(AutogroupsConfig, AutogroupsConfigAdmin)
|
||||
6
allianceauth/eveonline/autogroups/apps.py
Normal file
6
allianceauth/eveonline/autogroups/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class EveAutogroupsConfig(AppConfig):
|
||||
name = 'allianceauth.eveonline.autogroups'
|
||||
label = 'eve_autogroups'
|
||||
77
allianceauth/eveonline/autogroups/migrations/0001_initial.py
Normal file
77
allianceauth/eveonline/autogroups/migrations/0001_initial.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.5 on 2017-09-29 14:44
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0015_user_profiles'),
|
||||
('auth', '0008_alter_user_username_max_length'),
|
||||
('eveonline', '0009_on_delete'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AutogroupsConfig',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('corp_groups', models.BooleanField(default=False, help_text='Setting this to false will delete all the created groups.')),
|
||||
('corp_group_prefix', models.CharField(blank=True, default='Corp ', max_length=50)),
|
||||
('corp_name_source', models.CharField(choices=[('ticker', 'Ticker'), ('name', 'Full name')], default='name', max_length=20)),
|
||||
('alliance_groups', models.BooleanField(default=False, help_text='Setting this to false will delete all the created groups.')),
|
||||
('alliance_group_prefix', models.CharField(blank=True, default='Alliance ', max_length=50)),
|
||||
('alliance_name_source', models.CharField(choices=[('ticker', 'Ticker'), ('name', 'Full name')], default='name', max_length=20)),
|
||||
('replace_spaces', models.BooleanField(default=False)),
|
||||
('replace_spaces_with', models.CharField(blank=True, default='', help_text='Any spaces in the group name will be replaced with this.', max_length=10)),
|
||||
('states', models.ManyToManyField(related_name='autogroups', to='authentication.State')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ManagedGroup',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ManagedAllianceGroup',
|
||||
fields=[
|
||||
('managedgroup_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='eve_autogroups.ManagedGroup')),
|
||||
('alliance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveAllianceInfo')),
|
||||
],
|
||||
bases=('eve_autogroups.managedgroup',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ManagedCorpGroup',
|
||||
fields=[
|
||||
('managedgroup_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='eve_autogroups.ManagedGroup')),
|
||||
('corp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')),
|
||||
],
|
||||
bases=('eve_autogroups.managedgroup',),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='managedgroup',
|
||||
name='config',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.AutogroupsConfig'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='managedgroup',
|
||||
name='group',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='autogroupsconfig',
|
||||
name='alliance_managed_groups',
|
||||
field=models.ManyToManyField(help_text="A list of alliance groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='alliance_managed_config', through='eve_autogroups.ManagedAllianceGroup', to='auth.Group'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='autogroupsconfig',
|
||||
name='corp_managed_groups',
|
||||
field=models.ManyToManyField(help_text="A list of corporation groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='corp_managed_config', through='eve_autogroups.ManagedCorpGroup', to='auth.Group'),
|
||||
),
|
||||
]
|
||||
238
allianceauth/eveonline/autogroups/models.py
Normal file
238
allianceauth/eveonline/autogroups/models.py
Normal file
@@ -0,0 +1,238 @@
|
||||
import logging
|
||||
from django.db import models, transaction
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from allianceauth.authentication.models import State
|
||||
from allianceauth.eveonline.models import EveCorporationInfo, EveAllianceInfo
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_users_for_state(state: State):
|
||||
return User.objects.select_related('profile').prefetch_related('profile__main_character')\
|
||||
.filter(profile__state__pk=state.pk)
|
||||
|
||||
|
||||
class AutogroupsConfigManager(models.Manager):
|
||||
def update_groups_for_state(self, state: State):
|
||||
"""
|
||||
Update all the Group memberships for the users
|
||||
who have State
|
||||
:param state: State to update for
|
||||
:return:
|
||||
"""
|
||||
users = get_users_for_state(state)
|
||||
for config in self.filter(states=state):
|
||||
logger.debug("in state loop")
|
||||
for user in users:
|
||||
logger.debug("in user loop for {}".format(user))
|
||||
config.update_group_membership_for_user(user)
|
||||
|
||||
def update_groups_for_user(self, user: User, state: State = None):
|
||||
"""
|
||||
Update the Group memberships for the given users state
|
||||
:param user: User to update for
|
||||
:param state: State to update user for
|
||||
:return:
|
||||
"""
|
||||
if state is None:
|
||||
state = user.profile.state
|
||||
for config in self.filter(states=state):
|
||||
config.update_group_membership_for_user(user)
|
||||
|
||||
|
||||
class AutogroupsConfig(models.Model):
|
||||
OPT_TICKER = 'ticker'
|
||||
OPT_NAME = 'name'
|
||||
NAME_OPTIONS = (
|
||||
(OPT_TICKER, 'Ticker'),
|
||||
(OPT_NAME, 'Full name'),
|
||||
)
|
||||
|
||||
states = models.ManyToManyField(State, related_name='autogroups')
|
||||
|
||||
corp_groups = models.BooleanField(default=False,
|
||||
help_text="Setting this to false will delete all the created groups.")
|
||||
corp_group_prefix = models.CharField(max_length=50, default='Corp ', blank=True)
|
||||
corp_name_source = models.CharField(max_length=20, choices=NAME_OPTIONS, default=OPT_NAME)
|
||||
|
||||
alliance_groups = models.BooleanField(default=False,
|
||||
help_text="Setting this to false will delete all the created groups.")
|
||||
alliance_group_prefix = models.CharField(max_length=50, default='Alliance ', blank=True)
|
||||
alliance_name_source = models.CharField(max_length=20, choices=NAME_OPTIONS, default=OPT_NAME)
|
||||
|
||||
corp_managed_groups = models.ManyToManyField(
|
||||
Group, through='ManagedCorpGroup', related_name='corp_managed_config',
|
||||
help_text='A list of corporation groups created and maintained by this AutogroupConfig. '
|
||||
'You should not edit this list unless you know what you\'re doing.')
|
||||
|
||||
alliance_managed_groups = models.ManyToManyField(
|
||||
Group, through='ManagedAllianceGroup', related_name='alliance_managed_config',
|
||||
help_text='A list of alliance groups created and maintained by this AutogroupConfig. '
|
||||
'You should not edit this list unless you know what you\'re doing.')
|
||||
|
||||
replace_spaces = models.BooleanField(default=False)
|
||||
replace_spaces_with = models.CharField(
|
||||
max_length=10, default='', blank=True,
|
||||
help_text='Any spaces in the group name will be replaced with this.')
|
||||
|
||||
objects = AutogroupsConfigManager()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AutogroupsConfig, self).__init__(*args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
return 'States: ' + (' '.join(list(self.states.all().values_list('name', flat=True))) if self.pk else str(None))
|
||||
|
||||
def update_all_states_group_membership(self):
|
||||
list(map(self.update_group_membership_for_state, self.states.all()))
|
||||
|
||||
def update_group_membership_for_state(self, state: State):
|
||||
list(map(self.update_group_membership_for_user, get_users_for_state(state)))
|
||||
|
||||
@transaction.atomic
|
||||
def update_group_membership_for_user(self, user: User):
|
||||
self.update_alliance_group_membership(user)
|
||||
self.update_corp_group_membership(user)
|
||||
|
||||
def user_entitled_to_groups(self, user: User) -> bool:
|
||||
try:
|
||||
return user.profile.state in self.states.all()
|
||||
except ObjectDoesNotExist:
|
||||
return False
|
||||
|
||||
@transaction.atomic
|
||||
def update_alliance_group_membership(self, user: User):
|
||||
group = None
|
||||
try:
|
||||
if not self.alliance_groups or not self.user_entitled_to_groups(user):
|
||||
logger.debug('User {} does not have required state'.format(user))
|
||||
return
|
||||
else:
|
||||
alliance = user.profile.main_character.alliance
|
||||
if alliance is None:
|
||||
return
|
||||
group = self.get_alliance_group(alliance)
|
||||
except EveAllianceInfo.DoesNotExist:
|
||||
logger.warning('User {} main characters alliance does not exist in the database.'
|
||||
' Group membership not updated'.format(user))
|
||||
except AttributeError:
|
||||
logger.warning('User {} does not have a main character. Group membership not updated'.format(user))
|
||||
finally:
|
||||
self.remove_user_from_corp_groups(user, except_group=group)
|
||||
if group is not None:
|
||||
user.groups.add(group)
|
||||
|
||||
@transaction.atomic
|
||||
def update_corp_group_membership(self, user: User):
|
||||
group = None
|
||||
try:
|
||||
if not self.corp_groups or not self.user_entitled_to_groups(user):
|
||||
logger.debug('User {} does not have required state'.format(user))
|
||||
else:
|
||||
corp = user.profile.main_character.corporation
|
||||
group = self.get_corp_group(corp)
|
||||
except EveCorporationInfo.DoesNotExist:
|
||||
logger.warning('User {} main characters corporation does not exist in the database.'
|
||||
' Group membership not updated'.format(user))
|
||||
except AttributeError:
|
||||
logger.warning('User {} does not have a main character. Group membership not updated'.format(user))
|
||||
finally:
|
||||
self.remove_user_from_corp_groups(user, except_group=group)
|
||||
if group is not None:
|
||||
user.groups.add(group)
|
||||
|
||||
@transaction.atomic
|
||||
def remove_user_from_alliance_groups(self, user: User, except_group: Group = None):
|
||||
remove_groups = user.groups.filter(pk__in=self.alliance_managed_groups.all().values_list('pk', flat=True))
|
||||
if except_group is not None:
|
||||
remove_groups = remove_groups.exclude(pk=except_group.pk)
|
||||
list(map(user.groups.remove, remove_groups))
|
||||
|
||||
@transaction.atomic
|
||||
def remove_user_from_corp_groups(self, user: User, except_group: Group = None):
|
||||
remove_groups = user.groups.filter(pk__in=self.corp_managed_groups.all().values_list('pk', flat=True))
|
||||
if except_group is not None:
|
||||
remove_groups = remove_groups.exclude(pk=except_group.pk)
|
||||
list(map(user.groups.remove, remove_groups))
|
||||
|
||||
def get_alliance_group(self, alliance: EveAllianceInfo) -> Group:
|
||||
return self.create_alliance_group(alliance)
|
||||
|
||||
def get_corp_group(self, corp: EveCorporationInfo) -> Group:
|
||||
return self.create_corp_group(corp)
|
||||
|
||||
@transaction.atomic
|
||||
def create_alliance_group(self, alliance: EveAllianceInfo) -> Group:
|
||||
group, created = Group.objects.get_or_create(name=self.get_alliance_group_name(alliance))
|
||||
if created:
|
||||
ManagedAllianceGroup.objects.create(group=group, config=self, alliance=alliance)
|
||||
return group
|
||||
|
||||
@transaction.atomic
|
||||
def create_corp_group(self, corp: EveCorporationInfo) -> Group:
|
||||
group, created = Group.objects.get_or_create(name=self.get_corp_group_name(corp))
|
||||
if created:
|
||||
ManagedCorpGroup.objects.create(group=group, config=self, corp=corp)
|
||||
return group
|
||||
|
||||
def delete_alliance_managed_groups(self):
|
||||
"""
|
||||
Deletes ALL managed alliance groups
|
||||
"""
|
||||
self.alliance_managed_groups.all().delete()
|
||||
|
||||
def delete_corp_managed_groups(self):
|
||||
"""
|
||||
Deletes ALL managed corp groups
|
||||
"""
|
||||
self.corp_managed_groups.all().delete()
|
||||
|
||||
def get_alliance_group_name(self, alliance: EveAllianceInfo) -> str:
|
||||
if self.alliance_name_source == self.OPT_TICKER:
|
||||
name = alliance.alliance_ticker
|
||||
elif self.alliance_name_source == self.OPT_NAME:
|
||||
name = alliance.alliance_name
|
||||
else:
|
||||
raise NameSourceException('Not a valid name source')
|
||||
return self._replace_spaces(self.alliance_group_prefix + name)
|
||||
|
||||
def get_corp_group_name(self, corp: EveCorporationInfo) -> str:
|
||||
if self.corp_name_source == self.OPT_TICKER:
|
||||
name = corp.corporation_ticker
|
||||
elif self.corp_name_source == self.OPT_NAME:
|
||||
name = corp.corporation_name
|
||||
else:
|
||||
raise NameSourceException('Not a valid name source')
|
||||
return self._replace_spaces(self.corp_group_prefix + name)
|
||||
|
||||
def _replace_spaces(self, name: str) -> str:
|
||||
"""
|
||||
Replace the spaces in the given name based on the config
|
||||
:param name: name to replace spaces in
|
||||
:return: name with spaces replaced with the configured character(s) or unchanged if configured
|
||||
"""
|
||||
if self.replace_spaces:
|
||||
return name.strip().replace(' ', str(self.replace_spaces_with))
|
||||
return name
|
||||
|
||||
|
||||
class ManagedGroup(models.Model):
|
||||
group = models.ForeignKey(Group, on_delete=models.CASCADE)
|
||||
config = models.ForeignKey(AutogroupsConfig, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class ManagedCorpGroup(ManagedGroup):
|
||||
corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class ManagedAllianceGroup(ManagedGroup):
|
||||
alliance = models.ForeignKey(EveAllianceInfo, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class NameSourceException(Exception):
|
||||
pass
|
||||
66
allianceauth/eveonline/autogroups/signals.py
Normal file
66
allianceauth/eveonline/autogroups/signals.py
Normal file
@@ -0,0 +1,66 @@
|
||||
import logging
|
||||
from django.dispatch import receiver
|
||||
from django.db.models.signals import pre_save, post_save, pre_delete, m2m_changed
|
||||
from allianceauth.authentication.models import UserProfile, State
|
||||
|
||||
from .models import AutogroupsConfig
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@receiver(pre_save, sender=AutogroupsConfig)
|
||||
def pre_save_config(sender, instance, *args, **kwargs):
|
||||
"""
|
||||
Checks if enable was toggled on group config and
|
||||
deletes groups if necessary.
|
||||
"""
|
||||
logger.debug("Received pre_save from {}".format(instance))
|
||||
if not instance.pk:
|
||||
# new model being created
|
||||
return
|
||||
try:
|
||||
old_instance = AutogroupsConfig.objects.get(pk=instance.pk)
|
||||
|
||||
# Check if enable was toggled, delete groups?
|
||||
if old_instance.alliance_groups is True and instance.alliance_groups is False:
|
||||
instance.delete_alliance_managed_groups()
|
||||
|
||||
if old_instance.corp_groups is True and instance.corp_groups is False:
|
||||
instance.delete_corp_managed_groups()
|
||||
except AutogroupsConfig.DoesNotExist:
|
||||
pass
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=AutogroupsConfig)
|
||||
def pre_delete_config(sender, instance, *args, **kwargs):
|
||||
"""
|
||||
Delete groups on deleting config
|
||||
"""
|
||||
instance.delete_corp_managed_groups()
|
||||
instance.delete_alliance_managed_groups()
|
||||
|
||||
|
||||
@receiver(post_save, sender=UserProfile)
|
||||
def check_groups_on_profile_update(sender, instance, created, *args, **kwargs):
|
||||
"""
|
||||
Trigger check when main character or state changes.
|
||||
"""
|
||||
update_fields = kwargs.pop('update_fields', []) or []
|
||||
if 'main_character' in update_fields or 'state' in update_fields:
|
||||
AutogroupsConfig.objects.update_groups_for_user(instance.user)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=AutogroupsConfig.states.through)
|
||||
def autogroups_states_changed(sender, instance, action, reverse, model, pk_set, *args, **kwargs):
|
||||
"""
|
||||
Trigger group membership update when a state is added or removed from
|
||||
an autogroup config.
|
||||
"""
|
||||
if action.startswith('post_'):
|
||||
for pk in pk_set:
|
||||
try:
|
||||
state = State.objects.get(pk=pk)
|
||||
instance.update_group_membership_for_state(state)
|
||||
except State.DoesNotExist:
|
||||
# Deleted States handled by the profile state change
|
||||
pass
|
||||
27
allianceauth/eveonline/autogroups/tests/__init__.py
Normal file
27
allianceauth/eveonline/autogroups/tests/__init__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from unittest import mock
|
||||
from django.db.models.signals import pre_save, post_save, pre_delete, m2m_changed
|
||||
from allianceauth.authentication.models import UserProfile
|
||||
from allianceauth.authentication.signals import state_changed
|
||||
from allianceauth.eveonline.models import EveCharacter
|
||||
from .. import signals
|
||||
from ..models import AutogroupsConfig
|
||||
|
||||
MODULE_PATH = 'allianceauth.eveonline.autogroups'
|
||||
|
||||
|
||||
def patch(target, *args, **kwargs):
|
||||
return mock.patch('{}{}'.format(MODULE_PATH, target), *args, **kwargs)
|
||||
|
||||
|
||||
def connect_signals():
|
||||
pre_save.connect(receiver=signals.pre_save_config, sender=AutogroupsConfig)
|
||||
pre_delete.connect(receiver=signals.pre_delete_config, sender=AutogroupsConfig)
|
||||
post_save.connect(receiver=signals.check_groups_on_profile_update, sender=UserProfile)
|
||||
m2m_changed.connect(receiver=signals.autogroups_states_changed, sender=AutogroupsConfig.states.through)
|
||||
|
||||
|
||||
def disconnect_signals():
|
||||
pre_save.disconnect(receiver=signals.pre_save_config, sender=AutogroupsConfig)
|
||||
pre_delete.disconnect(receiver=signals.pre_delete_config, sender=AutogroupsConfig)
|
||||
post_save.disconnect(receiver=signals.check_groups_on_profile_update, sender=UserProfile)
|
||||
m2m_changed.disconnect(receiver=signals.autogroups_states_changed, sender=AutogroupsConfig.states.through)
|
||||
34
allianceauth/eveonline/autogroups/tests/test_managers.py
Normal file
34
allianceauth/eveonline/autogroups/tests/test_managers.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from django.test import TestCase
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from ..models import AutogroupsConfig
|
||||
from . import patch
|
||||
|
||||
|
||||
class AutogroupsConfigManagerTestCase(TestCase):
|
||||
|
||||
def test_update_groups_for_state(self, ):
|
||||
member = AuthUtils.create_member('test member')
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.states.add(member.profile.state)
|
||||
|
||||
with patch('.models.AutogroupsConfig.update_group_membership_for_user') as update_group_membership_for_user:
|
||||
AutogroupsConfig.objects.update_groups_for_state(member.profile.state)
|
||||
|
||||
self.assertTrue(update_group_membership_for_user.called)
|
||||
self.assertEqual(update_group_membership_for_user.call_count, 1)
|
||||
args, kwargs = update_group_membership_for_user.call_args
|
||||
self.assertEqual(args[0], member)
|
||||
|
||||
def test_update_groups_for_user(self):
|
||||
member = AuthUtils.create_member('test member')
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.states.add(member.profile.state)
|
||||
|
||||
with patch('.models.AutogroupsConfig.update_group_membership_for_user') as update_group_membership_for_user:
|
||||
AutogroupsConfig.objects.update_groups_for_user(member)
|
||||
|
||||
self.assertTrue(update_group_membership_for_user.called)
|
||||
self.assertEqual(update_group_membership_for_user.call_count, 1)
|
||||
args, kwargs = update_group_membership_for_user.call_args
|
||||
self.assertEqual(args[0], member)
|
||||
342
allianceauth/eveonline/autogroups/tests/test_models.py
Normal file
342
allianceauth/eveonline/autogroups/tests/test_models.py
Normal file
@@ -0,0 +1,342 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo, EveAllianceInfo
|
||||
|
||||
from ..models import AutogroupsConfig, get_users_for_state
|
||||
|
||||
|
||||
from . import patch, connect_signals, disconnect_signals
|
||||
|
||||
|
||||
class AutogroupsConfigTestCase(TestCase):
|
||||
def setUp(self):
|
||||
# Disconnect signals
|
||||
disconnect_signals()
|
||||
|
||||
self.member = AuthUtils.create_member('test user')
|
||||
|
||||
state = AuthUtils.get_member_state()
|
||||
|
||||
self.alliance = EveAllianceInfo.objects.create(
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
alliance_ticker='TIKR',
|
||||
executor_corp_id='2345',
|
||||
)
|
||||
|
||||
self.corp = EveCorporationInfo.objects.create(
|
||||
corporation_id='2345',
|
||||
corporation_name='corp name',
|
||||
corporation_ticker='TIKK',
|
||||
member_count=10,
|
||||
alliance=self.alliance,
|
||||
)
|
||||
|
||||
state.member_alliances.add(self.alliance)
|
||||
state.member_corporations.add(self.corp)
|
||||
|
||||
def tearDown(self):
|
||||
# Reconnect signals
|
||||
connect_signals()
|
||||
|
||||
def test_get_users_for_state(self):
|
||||
result = get_users_for_state(self.member.profile.state)
|
||||
|
||||
self.assertIn(self.member, result)
|
||||
self.assertEqual(len(result), 1)
|
||||
|
||||
@patch('.models.AutogroupsConfig.update_alliance_group_membership')
|
||||
@patch('.models.AutogroupsConfig.update_corp_group_membership')
|
||||
def test_update_group_membership(self, update_corp, update_alliance):
|
||||
agc = AutogroupsConfig.objects.create()
|
||||
agc.update_group_membership_for_user(self.member)
|
||||
|
||||
self.assertTrue(update_corp.called)
|
||||
self.assertTrue(update_alliance.called)
|
||||
|
||||
args, kwargs = update_corp.call_args
|
||||
self.assertEqual(args[0], self.member)
|
||||
|
||||
args, kwargs = update_alliance.call_args
|
||||
self.assertEqual(args[0], self.member)
|
||||
|
||||
def test_update_alliance_group_membership(self):
|
||||
obj = AutogroupsConfig.objects.create(alliance_groups=True)
|
||||
obj.states.add(AuthUtils.get_member_state())
|
||||
char = EveCharacter.objects.create(
|
||||
character_id='1234',
|
||||
character_name='test character',
|
||||
corporation_id='2345',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
self.member.profile.main_character = char
|
||||
self.member.profile.save()
|
||||
|
||||
pre_groups = self.member.groups.all()
|
||||
|
||||
# Act
|
||||
obj.update_alliance_group_membership(self.member)
|
||||
|
||||
group = obj.create_alliance_group(self.alliance)
|
||||
group_qs = Group.objects.filter(pk=group.pk)
|
||||
|
||||
self.assertIn(group, self.member.groups.all())
|
||||
self.assertQuerysetEqual(self.member.groups.all(), map(repr, pre_groups | group_qs), ordered=False)
|
||||
|
||||
def test_update_alliance_group_membership_no_main_character(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.states.add(AuthUtils.get_member_state())
|
||||
|
||||
# Act
|
||||
obj.update_alliance_group_membership(self.member)
|
||||
|
||||
group = obj.get_alliance_group(self.alliance)
|
||||
|
||||
self.assertNotIn(group, self.member.groups.all())
|
||||
|
||||
def test_update_alliance_group_membership_no_alliance_model(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.states.add(AuthUtils.get_member_state())
|
||||
char = EveCharacter.objects.create(
|
||||
character_id='1234',
|
||||
character_name='test character',
|
||||
corporation_id='2345',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3459',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
self.member.profile.main_character = char
|
||||
self.member.profile.save()
|
||||
|
||||
# Act
|
||||
obj.update_alliance_group_membership(self.member)
|
||||
|
||||
group = obj.get_alliance_group(self.alliance)
|
||||
|
||||
self.assertNotIn(group, self.member.groups.all())
|
||||
|
||||
def test_update_corp_group_membership(self):
|
||||
obj = AutogroupsConfig.objects.create(corp_groups=True)
|
||||
obj.states.add(AuthUtils.get_member_state())
|
||||
char = EveCharacter.objects.create(
|
||||
character_id='1234',
|
||||
character_name='test character',
|
||||
corporation_id='2345',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
self.member.profile.main_character = char
|
||||
self.member.profile.save()
|
||||
|
||||
pre_groups = self.member.groups.all()
|
||||
|
||||
# Act
|
||||
obj.update_corp_group_membership(self.member)
|
||||
|
||||
group = obj.get_corp_group(self.corp)
|
||||
group_qs = Group.objects.filter(pk=group.pk)
|
||||
|
||||
self.assertIn(group, self.member.groups.all())
|
||||
self.assertQuerysetEqual(self.member.groups.all(), map(repr, pre_groups | group_qs), ordered=False)
|
||||
|
||||
def test_update_corp_group_membership_no_state(self):
|
||||
obj = AutogroupsConfig.objects.create(corp_groups=True)
|
||||
char = EveCharacter.objects.create(
|
||||
character_id='1234',
|
||||
character_name='test character',
|
||||
corporation_id='2345',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
self.member.profile.main_character = char
|
||||
self.member.profile.save()
|
||||
|
||||
pre_groups = list(self.member.groups.all())
|
||||
|
||||
# Act
|
||||
obj.update_corp_group_membership(self.member)
|
||||
|
||||
group = obj.get_corp_group(self.corp)
|
||||
|
||||
post_groups = list(self.member.groups.all())
|
||||
|
||||
self.assertNotIn(group, post_groups)
|
||||
self.assertListEqual(pre_groups, post_groups)
|
||||
|
||||
def test_update_corp_group_membership_no_main_character(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.states.add(AuthUtils.get_member_state())
|
||||
|
||||
# Act
|
||||
obj.update_corp_group_membership(self.member)
|
||||
|
||||
group = obj.get_corp_group(self.corp)
|
||||
|
||||
self.assertNotIn(group, self.member.groups.all())
|
||||
|
||||
def test_update_corp_group_membership_no_corp_model(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.states.add(AuthUtils.get_member_state())
|
||||
char = EveCharacter.objects.create(
|
||||
character_id='1234',
|
||||
character_name='test character',
|
||||
corporation_id='2348',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
self.member.profile.main_character = char
|
||||
self.member.profile.save()
|
||||
|
||||
# Act
|
||||
obj.update_corp_group_membership(self.member)
|
||||
|
||||
group = obj.get_corp_group(self.corp)
|
||||
|
||||
self.assertNotIn(group, self.member.groups.all())
|
||||
|
||||
def test_remove_user_from_alliance_groups(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
result = obj.get_alliance_group(self.alliance)
|
||||
|
||||
result.user_set.add(self.member)
|
||||
|
||||
self.assertIn(result, self.member.groups.all())
|
||||
|
||||
# Act
|
||||
obj.remove_user_from_alliance_groups(self.member)
|
||||
|
||||
self.assertNotIn(result, self.member.groups.all())
|
||||
|
||||
def test_remove_user_from_corp_groups(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
result = obj.get_corp_group(self.corp)
|
||||
|
||||
result.user_set.add(self.member)
|
||||
|
||||
self.assertIn(result, self.member.groups.all())
|
||||
|
||||
# Act
|
||||
obj.remove_user_from_corp_groups(self.member)
|
||||
|
||||
self.assertNotIn(result, self.member.groups.all())
|
||||
|
||||
def test_get_alliance_group(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
result = obj.get_alliance_group(self.alliance)
|
||||
|
||||
group = Group.objects.get(name='Alliance alliance name')
|
||||
|
||||
self.assertEqual(result, group)
|
||||
self.assertEqual(obj.get_alliance_group_name(self.alliance), result.name)
|
||||
self.assertTrue(obj.alliance_managed_groups.filter(pk=result.pk).exists())
|
||||
|
||||
def test_get_corp_group(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
result = obj.get_corp_group(self.corp)
|
||||
|
||||
group = Group.objects.get(name='Corp corp name')
|
||||
|
||||
self.assertEqual(result, group)
|
||||
self.assertEqual(obj.get_corp_group_name(self.corp), group.name)
|
||||
self.assertTrue(obj.corp_managed_groups.filter(pk=group.pk).exists())
|
||||
|
||||
def test_create_alliance_group(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
result = obj.create_alliance_group(self.alliance)
|
||||
|
||||
group = Group.objects.get(name='Alliance alliance name')
|
||||
|
||||
self.assertEqual(result, group)
|
||||
self.assertEqual(obj.get_alliance_group_name(self.alliance), group.name)
|
||||
self.assertTrue(obj.alliance_managed_groups.filter(pk=group.pk).exists())
|
||||
|
||||
def test_create_corp_group(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
result = obj.create_corp_group(self.corp)
|
||||
|
||||
group = Group.objects.get(name='Corp corp name')
|
||||
|
||||
self.assertEqual(result, group)
|
||||
self.assertEqual(obj.get_corp_group_name(self.corp), group.name)
|
||||
self.assertTrue(obj.corp_managed_groups.filter(pk=group.pk).exists())
|
||||
|
||||
def test_delete_alliance_managed_groups(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.create_alliance_group(self.alliance)
|
||||
|
||||
self.assertTrue(obj.alliance_managed_groups.all().exists())
|
||||
|
||||
obj.delete_alliance_managed_groups()
|
||||
|
||||
self.assertFalse(obj.alliance_managed_groups.all().exists())
|
||||
|
||||
def test_delete_corp_managed_groups(self):
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
obj.create_corp_group(self.corp)
|
||||
|
||||
self.assertTrue(obj.corp_managed_groups.all().exists())
|
||||
|
||||
obj.delete_corp_managed_groups()
|
||||
|
||||
self.assertFalse(obj.corp_managed_groups.all().exists())
|
||||
|
||||
def test_get_alliance_group_name(self):
|
||||
obj = AutogroupsConfig()
|
||||
obj.replace_spaces = True
|
||||
obj.replace_spaces_with = '_'
|
||||
|
||||
result = obj.get_alliance_group_name(self.alliance)
|
||||
|
||||
self.assertEqual(result, 'Alliance_alliance_name')
|
||||
|
||||
def test_get_alliance_group_name_ticker(self):
|
||||
obj = AutogroupsConfig()
|
||||
obj.replace_spaces = True
|
||||
obj.replace_spaces_with = '_'
|
||||
obj.alliance_name_source = obj.OPT_TICKER
|
||||
|
||||
result = obj.get_alliance_group_name(self.alliance)
|
||||
|
||||
self.assertEqual(result, 'Alliance_TIKR')
|
||||
|
||||
def test_get_corp_group_name(self):
|
||||
obj = AutogroupsConfig()
|
||||
obj.replace_spaces = True
|
||||
obj.replace_spaces_with = '_'
|
||||
|
||||
result = obj.get_corp_group_name(self.corp)
|
||||
|
||||
self.assertEqual(result, 'Corp_corp_name')
|
||||
|
||||
def test_get_corp_group_name_ticker(self):
|
||||
obj = AutogroupsConfig()
|
||||
obj.replace_spaces = True
|
||||
obj.replace_spaces_with = '_'
|
||||
obj.corp_name_source = obj.OPT_TICKER
|
||||
|
||||
result = obj.get_corp_group_name(self.corp)
|
||||
|
||||
self.assertEqual(result, 'Corp_TIKK')
|
||||
|
||||
def test__replace_spaces(self):
|
||||
obj = AutogroupsConfig()
|
||||
obj.replace_spaces = True
|
||||
obj.replace_spaces_with = '*'
|
||||
name = ' test name '
|
||||
|
||||
result = obj._replace_spaces(name)
|
||||
|
||||
self.assertEqual(result, 'test*name')
|
||||
208
allianceauth/eveonline/autogroups/tests/test_signals.py
Normal file
208
allianceauth/eveonline/autogroups/tests/test_signals.py
Normal file
@@ -0,0 +1,208 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import Group, User
|
||||
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo, EveAllianceInfo
|
||||
|
||||
from ..models import AutogroupsConfig, ManagedAllianceGroup
|
||||
|
||||
from . import patch, disconnect_signals, connect_signals
|
||||
|
||||
|
||||
class SignalsTestCase(TestCase):
|
||||
def setUp(self):
|
||||
disconnect_signals()
|
||||
self.member = AuthUtils.create_member('test user')
|
||||
|
||||
state = AuthUtils.get_member_state()
|
||||
|
||||
self.char = EveCharacter.objects.create(
|
||||
character_id='1234',
|
||||
character_name='test character',
|
||||
corporation_id='2345',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
|
||||
self.member.profile.main_character = self.char
|
||||
self.member.profile.save()
|
||||
|
||||
self.alliance = EveAllianceInfo.objects.create(
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
alliance_ticker='TIKR',
|
||||
executor_corp_id='2345',
|
||||
)
|
||||
|
||||
self.corp = EveCorporationInfo.objects.create(
|
||||
corporation_id='2345',
|
||||
corporation_name='corp name',
|
||||
corporation_ticker='TIKK',
|
||||
member_count=10,
|
||||
alliance=self.alliance,
|
||||
)
|
||||
|
||||
state.member_alliances.add(self.alliance)
|
||||
state.member_corporations.add(self.corp)
|
||||
connect_signals()
|
||||
|
||||
@patch('.models.AutogroupsConfigManager.update_groups_for_user')
|
||||
def test_check_groups_on_profile_update_state(self, update_groups_for_user):
|
||||
# Trigger signal
|
||||
self.member.profile.state = AuthUtils.get_guest_state()
|
||||
self.member.profile.save()
|
||||
|
||||
self.assertTrue(update_groups_for_user.called)
|
||||
self.assertEqual(update_groups_for_user.call_count, 1)
|
||||
args, kwargs = update_groups_for_user.call_args
|
||||
self.assertEqual(args[0], self.member)
|
||||
|
||||
@patch('.models.AutogroupsConfigManager.update_groups_for_user')
|
||||
def test_check_groups_on_profile_update_main_character(self, update_groups_for_user):
|
||||
char = EveCharacter.objects.create(
|
||||
character_id='1266',
|
||||
character_name='test character2',
|
||||
corporation_id='2345',
|
||||
corporation_name='test corp',
|
||||
corporation_ticker='tickr',
|
||||
alliance_id='3456',
|
||||
alliance_name='alliance name',
|
||||
)
|
||||
# Trigger signal
|
||||
self.member.profile.main_character = char
|
||||
self.member.profile.save()
|
||||
|
||||
self.assertTrue(update_groups_for_user.called)
|
||||
self.assertEqual(update_groups_for_user.call_count, 1)
|
||||
args, kwargs = update_groups_for_user.call_args
|
||||
self.assertEqual(args[0], self.member)
|
||||
member = User.objects.get(pk=self.member.pk)
|
||||
self.assertEqual(member.profile.state, AuthUtils.get_member_state())
|
||||
|
||||
@patch('.models.AutogroupsConfigManager.update_groups_for_user')
|
||||
def test_check_groups_on_character_update(self, update_groups_for_user):
|
||||
"""
|
||||
Test update_groups_for_user is called when main_character properties
|
||||
are changed.
|
||||
"""
|
||||
|
||||
# Trigger signal
|
||||
self.member.profile.main_character.corporation_id = '2300'
|
||||
self.member.profile.main_character.save()
|
||||
|
||||
self.assertTrue(update_groups_for_user.called)
|
||||
self.assertEqual(update_groups_for_user.call_count, 1)
|
||||
args, kwargs = update_groups_for_user.call_args
|
||||
self.assertEqual(args[0], self.member)
|
||||
member = User.objects.get(pk=self.member.pk)
|
||||
self.assertEqual(member.profile.state, AuthUtils.get_member_state())
|
||||
|
||||
@patch('.models.AutogroupsConfig.delete_corp_managed_groups')
|
||||
@patch('.models.AutogroupsConfig.delete_alliance_managed_groups')
|
||||
def test_pre_save_config_deletes_alliance_groups(self, delete_alliance_managed_groups, delete_corp_managed_groups):
|
||||
"""
|
||||
Test that delete_alliance_managed_groups is called when the alliance_groups
|
||||
setting is toggled to False
|
||||
"""
|
||||
obj = AutogroupsConfig.objects.create(alliance_groups=True)
|
||||
|
||||
obj.create_alliance_group(self.alliance)
|
||||
|
||||
# Trigger signal
|
||||
obj.alliance_groups = False
|
||||
obj.save()
|
||||
|
||||
self.assertTrue(delete_alliance_managed_groups.called)
|
||||
self.assertFalse(delete_corp_managed_groups.called)
|
||||
self.assertEqual(delete_alliance_managed_groups.call_count, 1)
|
||||
|
||||
@patch('.models.AutogroupsConfig.delete_alliance_managed_groups')
|
||||
@patch('.models.AutogroupsConfig.delete_corp_managed_groups')
|
||||
def test_pre_save_config_deletes_corp_groups(self, delete_corp_managed_groups, delete_alliance_managed_groups):
|
||||
"""
|
||||
Test that delete_corp_managed_groups is called when the corp_groups
|
||||
setting is toggled to False
|
||||
"""
|
||||
obj = AutogroupsConfig.objects.create(corp_groups=True)
|
||||
|
||||
obj.create_corp_group(self.corp)
|
||||
|
||||
# Trigger signal
|
||||
obj.corp_groups = False
|
||||
obj.save()
|
||||
|
||||
self.assertTrue(delete_corp_managed_groups.called)
|
||||
self.assertFalse(delete_alliance_managed_groups.called)
|
||||
self.assertEqual(delete_corp_managed_groups.call_count, 1)
|
||||
|
||||
@patch('.models.AutogroupsConfig.delete_alliance_managed_groups')
|
||||
@patch('.models.AutogroupsConfig.delete_corp_managed_groups')
|
||||
def test_pre_save_config_does_nothing(self, delete_corp_managed_groups, delete_alliance_managed_groups):
|
||||
"""
|
||||
Test groups arent deleted if we arent setting the enabled params to False
|
||||
"""
|
||||
obj = AutogroupsConfig.objects.create(corp_groups=True)
|
||||
|
||||
obj.create_corp_group(self.corp)
|
||||
|
||||
# Trigger signal
|
||||
obj.alliance_groups = True
|
||||
obj.save()
|
||||
|
||||
self.assertFalse(delete_corp_managed_groups.called)
|
||||
self.assertFalse(delete_alliance_managed_groups.called)
|
||||
|
||||
@patch('.models.AutogroupsConfig.delete_alliance_managed_groups')
|
||||
@patch('.models.AutogroupsConfig.delete_corp_managed_groups')
|
||||
def test_pre_delete_config(self, delete_corp_managed_groups, delete_alliance_managed_groups):
|
||||
"""
|
||||
Test groups are deleted if config is deleted
|
||||
"""
|
||||
obj = AutogroupsConfig.objects.create()
|
||||
|
||||
# Trigger signal
|
||||
obj.delete()
|
||||
|
||||
self.assertTrue(delete_corp_managed_groups.called)
|
||||
self.assertTrue(delete_alliance_managed_groups.called)
|
||||
|
||||
@patch('.models.AutogroupsConfig.update_group_membership_for_state')
|
||||
def test_autogroups_states_changed_add(self, update_group_membership_for_state):
|
||||
"""
|
||||
Test update_group_membership_for_state is called when a state is added to
|
||||
the AutogroupsConfig
|
||||
"""
|
||||
obj = AutogroupsConfig.objects.create(alliance_groups=True)
|
||||
state = AuthUtils.get_member_state()
|
||||
|
||||
# Trigger
|
||||
obj.states.add(state)
|
||||
|
||||
self.assertTrue(update_group_membership_for_state.called)
|
||||
self.assertEqual(update_group_membership_for_state.call_count, 1)
|
||||
args, kwargs = update_group_membership_for_state.call_args
|
||||
self.assertEqual(args[0], state)
|
||||
|
||||
@patch('.models.AutogroupsConfig.update_group_membership_for_state')
|
||||
def test_autogroups_states_changed_remove(self, update_group_membership_for_state):
|
||||
"""
|
||||
Test update_group_membership_for_state is called when a state is removed from
|
||||
the AutogroupsConfig
|
||||
"""
|
||||
obj = AutogroupsConfig.objects.create(alliance_groups=True)
|
||||
state = AuthUtils.get_member_state()
|
||||
|
||||
disconnect_signals()
|
||||
obj.states.add(state)
|
||||
connect_signals()
|
||||
|
||||
# Trigger
|
||||
obj.states.remove(state)
|
||||
|
||||
self.assertTrue(update_group_membership_for_state.called)
|
||||
self.assertEqual(update_group_membership_for_state.call_count, 1)
|
||||
args, kwargs = update_group_membership_for_state.call_args
|
||||
self.assertEqual(args[0], state)
|
||||
Reference in New Issue
Block a user