diff --git a/allianceauth/groupmanagement/admin.py b/allianceauth/groupmanagement/admin.py index 09d2aaa1..d4d3d659 100644 --- a/allianceauth/groupmanagement/admin.py +++ b/allianceauth/groupmanagement/admin.py @@ -8,8 +8,8 @@ from .models import GroupRequest class AuthGroupInlineAdmin(admin.StackedInline): model = AuthGroup - filter_horizontal = ('group_leaders', 'states',) - fields = ('description', 'group_leaders', 'states', 'internal', 'hidden', 'open', 'public') + filter_horizontal = ('group_leaders', 'group_leader_groups', 'states',) + fields = ('description', 'group_leaders', 'group_leader_groups', 'states', 'internal', 'hidden', 'open', 'public') verbose_name_plural = 'Auth Settings' verbose_name = '' diff --git a/allianceauth/groupmanagement/managers.py b/allianceauth/groupmanagement/managers.py index 78aceb86..26d2795d 100644 --- a/allianceauth/groupmanagement/managers.py +++ b/allianceauth/groupmanagement/managers.py @@ -17,7 +17,8 @@ class GroupManager: @staticmethod def get_group_leaders_groups(user): - return Group.objects.select_related('authgroup').filter(authgroup__group_leaders__in=[user]) + return Group.objects.select_related('authgroup').filter(authgroup__group_leaders__in=[user]) | \ + Group.objects.select_related('authgroup').filter(authgroup__group_leader_groups__in=user.groups.all()) @staticmethod def joinable_group(group, state): @@ -66,7 +67,7 @@ class GroupManager: :return: bool True if user can manage groups, False otherwise """ if user.is_authenticated: - return cls.has_management_permission(user) or user.leads_groups.all() + return cls.has_management_permission(user) or cls.get_group_leaders_groups(user) return False @classmethod diff --git a/allianceauth/groupmanagement/migrations/0012_group_leads.py b/allianceauth/groupmanagement/migrations/0012_group_leads.py new file mode 100644 index 00000000..0df7f9bc --- /dev/null +++ b/allianceauth/groupmanagement/migrations/0012_group_leads.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.8 on 2020-01-06 11:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0011_update_proxy_permissions'), + ('groupmanagement', '0011_requestlog_date'), + ] + + operations = [ + migrations.AddField( + model_name='authgroup', + name='group_leader_groups', + field=models.ManyToManyField(blank=True, help_text='Group leaders can process group requests for this group specifically. Use the auth.group_management permission to allow a user to manage all groups.', related_name='leads_group_groups', to='auth.Group'), + ) + ] diff --git a/allianceauth/groupmanagement/models.py b/allianceauth/groupmanagement/models.py index e8c1c913..563035b2 100644 --- a/allianceauth/groupmanagement/models.py +++ b/allianceauth/groupmanagement/models.py @@ -98,6 +98,11 @@ class AuthGroup(models.Model): help_text="Group leaders can process group requests for this group " "specifically. Use the auth.group_management permission to allow " "a user to manage all groups.") + # allow groups to be *group leads* + group_leader_groups = models.ManyToManyField(Group, related_name='leads_group_groups', blank=True, + help_text="Group leaders can process group requests for this group " + "specifically. Use the auth.group_management permission to allow " + "a user to manage all groups.") states = models.ManyToManyField(State, related_name='valid_states', blank=True, help_text="States listed here will have the ability to join this group provided " diff --git a/allianceauth/groupmanagement/tests.py b/allianceauth/groupmanagement/tests.py new file mode 100644 index 00000000..42e08a8c --- /dev/null +++ b/allianceauth/groupmanagement/tests.py @@ -0,0 +1,46 @@ +from unittest import mock + +from django.test import TestCase +from allianceauth.tests.auth_utils import AuthUtils +from allianceauth.eveonline.models import EveCorporationInfo, EveAllianceInfo, EveCharacter +from django.contrib.auth.models import User, Group +from allianceauth.groupmanagement.managers import GroupManager + +class GroupManagementVisibilityTestCase(TestCase): + @classmethod + def setUpTestData(cls): + cls.user = AuthUtils.create_user('test') + AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST') + cls.user.profile.refresh_from_db() + cls.alliance = EveAllianceInfo.objects.create(alliance_id='3', alliance_name='test alliance', alliance_ticker='TEST', executor_corp_id='2') + cls.corp = EveCorporationInfo.objects.create(corporation_id='2', corporation_name='test corp', corporation_ticker='TEST', alliance=cls.alliance, member_count=1) + cls.group1 = Group.objects.create(name='group1') + cls.group2 = Group.objects.create(name='group2') + cls.group3 = Group.objects.create(name='group3') + + def setUp(self): + self.user.refresh_from_db() + + def _refresh_user(self): + self.user = User.objects.get(pk=self.user.pk) + + + def test_can_manage_group(self): + + + self.group1.authgroup.group_leaders.add(self.user) + self.group2.authgroup.group_leader_groups.add(self.group1) + self._refresh_user() + groups = GroupManager.get_group_leaders_groups(self.user) + + self.assertIn(self.group1, groups) #avail due to user + self.assertNotIn(self.group2, groups) #not avail due to group + self.assertNotIn(self.group3, groups) #not avail at all + + self.user.groups.add(self.group1) + self._refresh_user() + groups = GroupManager.get_group_leaders_groups(self.user) + + self.assertIn(self.group1, groups) #avail due to user + self.assertIn(self.group2, groups) #avail due to group1 + self.assertNotIn(self.group3, groups) #not avail at all