mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-15 15:30:16 +02:00
Adding settings for users lists, showing all auto groups in groups
This commit is contained in:
parent
9d0a65a516
commit
0caac20d77
@ -19,6 +19,7 @@ from allianceauth.authentication.models import State, get_guest_state,\
|
|||||||
from allianceauth.hooks import get_hooks
|
from allianceauth.hooks import get_hooks
|
||||||
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo
|
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo
|
||||||
from allianceauth.eveonline.tasks import update_character
|
from allianceauth.eveonline.tasks import update_character
|
||||||
|
from .app_settings import *
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
||||||
_has_auto_groups = True
|
_has_auto_groups = True
|
||||||
@ -27,10 +28,6 @@ else:
|
|||||||
_has_auto_groups = False
|
_has_auto_groups = False
|
||||||
|
|
||||||
|
|
||||||
_USERS_MAX_GROUPS = 5
|
|
||||||
_USERS_MAX_CHARACTERS = 3
|
|
||||||
|
|
||||||
|
|
||||||
def make_service_hooks_update_groups_action(service):
|
def make_service_hooks_update_groups_action(service):
|
||||||
"""
|
"""
|
||||||
Make a admin action for the given service
|
Make a admin action for the given service
|
||||||
@ -324,7 +321,10 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
.filter(user=obj)\
|
.filter(user=obj)\
|
||||||
.order_by('character__character_name')
|
.order_by('character__character_name')
|
||||||
]
|
]
|
||||||
return list_2_html_w_tooltips(my_characters, _USERS_MAX_CHARACTERS)
|
return list_2_html_w_tooltips(
|
||||||
|
my_characters,
|
||||||
|
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
||||||
|
)
|
||||||
|
|
||||||
_characters.short_description = 'characters'
|
_characters.short_description = 'characters'
|
||||||
|
|
||||||
@ -347,7 +347,10 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
.order_by('name')
|
.order_by('name')
|
||||||
]
|
]
|
||||||
|
|
||||||
return list_2_html_w_tooltips(my_groups, _USERS_MAX_GROUPS)
|
return list_2_html_w_tooltips(
|
||||||
|
my_groups,
|
||||||
|
AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
||||||
|
)
|
||||||
|
|
||||||
_groups.short_description = 'groups'
|
_groups.short_description = 'groups'
|
||||||
|
|
||||||
|
46
allianceauth/authentication/app_settings.py
Normal file
46
allianceauth/authentication/app_settings.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_setting(
|
||||||
|
name: str,
|
||||||
|
default_value: object,
|
||||||
|
min_value: int = None,
|
||||||
|
max_value: int = None,
|
||||||
|
required_type: type = None
|
||||||
|
):
|
||||||
|
"""cleans the input for a custom setting
|
||||||
|
|
||||||
|
Will use `default_value` if settings does not exit or has the wrong type
|
||||||
|
or is outside define boundaries (for int only)
|
||||||
|
|
||||||
|
Need to define `required_type` if `default_value` is `None`
|
||||||
|
|
||||||
|
Will assume `min_value` of 0 for int (can be overriden)
|
||||||
|
|
||||||
|
Returns cleaned value for setting
|
||||||
|
"""
|
||||||
|
if default_value is None and not required_type:
|
||||||
|
raise ValueError('You must specify a required_type for None defaults')
|
||||||
|
|
||||||
|
if not required_type:
|
||||||
|
required_type = type(default_value)
|
||||||
|
|
||||||
|
if min_value is None and required_type == int:
|
||||||
|
min_value = 0
|
||||||
|
|
||||||
|
if (hasattr(settings, name)
|
||||||
|
and isinstance(getattr(settings, name), required_type)
|
||||||
|
and (min_value is None or getattr(settings, name) >= min_value)
|
||||||
|
and (max_value is None or getattr(settings, name) <= max_value)
|
||||||
|
):
|
||||||
|
return getattr(settings, name)
|
||||||
|
else:
|
||||||
|
return default_value
|
||||||
|
|
||||||
|
|
||||||
|
AUTHENTICATION_ADMIN_USERS_MAX_GROUPS = \
|
||||||
|
_clean_setting('AUTHENTICATION_ADMIN_USERS_MAX_GROUPS', 10)
|
||||||
|
|
||||||
|
AUTHENTICATION_ADMIN_USERS_MAX_CHARS = \
|
||||||
|
_clean_setting('AUTHENTICATION_ADMIN_USERS_MAX_CHARS', 5)
|
||||||
|
|
@ -2,6 +2,7 @@
|
|||||||
CSS for allianceauth admin site
|
CSS for allianceauth admin site
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* styling for profile pic */
|
||||||
.img-circle { border-radius: 50%; }
|
.img-circle { border-radius: 50%; }
|
||||||
.column-_profile_pic { width: 50px; }
|
.column-_profile_pic { width: 50px; }
|
||||||
|
|
||||||
|
0
allianceauth/authentication/tests/__init__.py
Normal file
0
allianceauth/authentication/tests/__init__.py
Normal file
@ -1,23 +1,28 @@
|
|||||||
from unittest import mock
|
from unittest import mock
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from django.test import TestCase
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
|
||||||
from .models import CharacterOwnership, UserProfile, State, get_guest_state, OwnershipRecord
|
|
||||||
from .backends import StateBackend
|
|
||||||
from .tasks import check_character_ownership
|
|
||||||
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo, EveAllianceInfo
|
|
||||||
from esi.models import Token
|
|
||||||
from esi.errors import IncompleteResponseError
|
|
||||||
from allianceauth.authentication.decorators import main_character_required
|
|
||||||
from django.test.client import RequestFactory
|
|
||||||
from django.http.response import HttpResponse
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
from django.conf import settings
|
|
||||||
from django.shortcuts import reverse
|
|
||||||
from django.core.management import call_command
|
|
||||||
from urllib import parse
|
from urllib import parse
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import AnonymousUser, User
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.http.response import HttpResponse
|
||||||
|
from django.shortcuts import reverse
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
|
||||||
|
|
||||||
|
from allianceauth.authentication.decorators import main_character_required
|
||||||
|
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo,\
|
||||||
|
EveAllianceInfo
|
||||||
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
from esi.errors import IncompleteResponseError
|
||||||
|
from esi.models import Token
|
||||||
|
|
||||||
|
from ..backends import StateBackend
|
||||||
|
from ..models import CharacterOwnership, UserProfile, State, get_guest_state,\
|
||||||
|
OwnershipRecord
|
||||||
|
from ..tasks import check_character_ownership
|
||||||
|
|
||||||
MODULE_PATH = 'allianceauth.authentication'
|
MODULE_PATH = 'allianceauth.authentication'
|
||||||
|
|
||||||
|
|
108
allianceauth/authentication/tests/test_app_settings.py
Normal file
108
allianceauth/authentication/tests/test_app_settings.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from .. import app_settings
|
||||||
|
|
||||||
|
MODULE_PATH = 'allianceauth.authentication'
|
||||||
|
|
||||||
|
class TestSetAppSetting(TestCase):
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_if_not_set(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
False,
|
||||||
|
)
|
||||||
|
self.assertEqual(result, False)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_if_not_set_for_none(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
None,
|
||||||
|
required_type=int
|
||||||
|
)
|
||||||
|
self.assertEqual(result, None)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_true_stays_true(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = True
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
False,
|
||||||
|
)
|
||||||
|
self.assertEqual(result, True)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_false_stays_false(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = False
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
False
|
||||||
|
)
|
||||||
|
self.assertEqual(result, False)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_for_invalid_type_bool(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
False
|
||||||
|
)
|
||||||
|
self.assertEqual(result, False)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_for_invalid_type_int(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
50
|
||||||
|
)
|
||||||
|
self.assertEqual(result, 50)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_if_below_minimum_1(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = -5
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
default_value=50
|
||||||
|
)
|
||||||
|
self.assertEqual(result, 50)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_if_below_minimum_2(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = -50
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
default_value=50,
|
||||||
|
min_value=-10
|
||||||
|
)
|
||||||
|
self.assertEqual(result, 50)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_for_invalid_type_int(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = 1000
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
default_value=50,
|
||||||
|
max_value=100
|
||||||
|
)
|
||||||
|
self.assertEqual(result, 50)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
|
def test_default_is_none_needs_required_type(self, mock_settings):
|
||||||
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
result = app_settings._clean_setting(
|
||||||
|
'TEST_SETTING_DUMMY',
|
||||||
|
default_value=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -35,6 +35,49 @@ class AuthGroupInlineAdmin(admin.StackedInline):
|
|||||||
return request.user.has_perm('auth.change_group')
|
return request.user.has_perm('auth.change_group')
|
||||||
|
|
||||||
|
|
||||||
|
if _has_auto_groups:
|
||||||
|
class IsAutoGroupFilter(admin.SimpleListFilter):
|
||||||
|
title = 'auto group'
|
||||||
|
parameter_name = 'auto_group'
|
||||||
|
|
||||||
|
def lookups(self, request, model_admin):
|
||||||
|
return (
|
||||||
|
('Yes', 'Yes'),
|
||||||
|
('No', 'No'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def queryset(self, request, queryset):
|
||||||
|
value = self.value()
|
||||||
|
if value == 'Yes':
|
||||||
|
return queryset.exclude(
|
||||||
|
managedalliancegroup__exact=None,
|
||||||
|
managedcorpgroup__exact=None
|
||||||
|
)
|
||||||
|
elif value == 'No':
|
||||||
|
return queryset.filter(managedalliancegroup__exact=None).filter(managedcorpgroup__exact=None)
|
||||||
|
else:
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class HasLeaderFilter(admin.SimpleListFilter):
|
||||||
|
title = 'has leader'
|
||||||
|
parameter_name = 'has_leader'
|
||||||
|
|
||||||
|
def lookups(self, request, model_admin):
|
||||||
|
return (
|
||||||
|
('Yes', 'Yes'),
|
||||||
|
('No', 'No'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def queryset(self, request, queryset):
|
||||||
|
value = self.value()
|
||||||
|
if value == 'Yes':
|
||||||
|
return queryset.filter(authgroup__group_leaders__isnull=False)
|
||||||
|
elif value == 'No':
|
||||||
|
return queryset.filter(authgroup__group_leaders__isnull=True)
|
||||||
|
else:
|
||||||
|
return queryset
|
||||||
|
|
||||||
class GroupAdmin(admin.ModelAdmin):
|
class GroupAdmin(admin.ModelAdmin):
|
||||||
list_select_related = True
|
list_select_related = True
|
||||||
ordering = ('name', )
|
ordering = ('name', )
|
||||||
@ -50,7 +93,9 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
'authgroup__internal',
|
'authgroup__internal',
|
||||||
'authgroup__hidden',
|
'authgroup__hidden',
|
||||||
'authgroup__open',
|
'authgroup__open',
|
||||||
'authgroup__public'
|
'authgroup__public',
|
||||||
|
IsAutoGroupFilter,
|
||||||
|
HasLeaderFilter
|
||||||
)
|
)
|
||||||
search_fields = ('name', 'authgroup__description')
|
search_fields = ('name', 'authgroup__description')
|
||||||
|
|
||||||
@ -59,10 +104,6 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super().get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
if _has_auto_groups:
|
|
||||||
qs = qs\
|
|
||||||
.filter(managedalliancegroup__exact=None)\
|
|
||||||
.filter(managedcorpgroup__exact=None)
|
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
member_count=Count('user', distinct=True),
|
member_count=Count('user', distinct=True),
|
||||||
)
|
)
|
||||||
@ -82,9 +123,15 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
has_leader.boolean = True
|
has_leader.boolean = True
|
||||||
|
|
||||||
|
|
||||||
def _properties(self, obj):
|
def _properties(self, obj):
|
||||||
properties = list()
|
properties = list()
|
||||||
if obj.authgroup.internal:
|
if _has_auto_groups and (
|
||||||
|
obj.managedalliancegroup_set.exists()
|
||||||
|
or obj.managedcorpgroup_set.exists()
|
||||||
|
):
|
||||||
|
properties.append('Auto Group')
|
||||||
|
elif obj.authgroup.internal:
|
||||||
properties.append('Internal')
|
properties.append('Internal')
|
||||||
else:
|
else:
|
||||||
if obj.authgroup.hidden:
|
if obj.authgroup.hidden:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user