mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-09 20:40:17 +02:00
Merge branch 'master' of https://gitlab.com/allianceauth/allianceauth into v2.9.x
This commit is contained in:
commit
192d286cf2
@ -7,15 +7,21 @@ include:
|
|||||||
- template: Dependency-Scanning.gitlab-ci.yml
|
- template: Dependency-Scanning.gitlab-ci.yml
|
||||||
- template: Security/SAST.gitlab-ci.yml
|
- template: Security/SAST.gitlab-ci.yml
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- apt-get update && apt-get install redis-server -y
|
||||||
|
- redis-server --daemonize yes
|
||||||
|
- python -V
|
||||||
|
- pip install wheel tox
|
||||||
|
|
||||||
sast:
|
sast:
|
||||||
stage: gitlab
|
stage: gitlab
|
||||||
|
before_script: []
|
||||||
|
|
||||||
dependency_scanning:
|
dependency_scanning:
|
||||||
stage: gitlab
|
stage: gitlab
|
||||||
before_script:
|
before_script:
|
||||||
- apt-get update && apt-get install redis-server libmariadbclient-dev -y
|
- apt-get update && apt-get install redis-server libmariadbclient-dev -y
|
||||||
- redis-server --daemonize yes
|
- redis-server --daemonize yes
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
- python -V
|
||||||
- pip install wheel tox
|
- pip install wheel tox
|
||||||
|
|
||||||
@ -23,12 +29,6 @@ test-3.7-core:
|
|||||||
image: python:3.7-buster
|
image: python:3.7-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py37-core
|
- tox -e py37-core
|
||||||
before_script:
|
|
||||||
- apt-get update && apt-get install redis-server -y
|
|
||||||
- redis-server --daemonize yes
|
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
|
||||||
- pip install wheel tox
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@ -38,12 +38,6 @@ test-3.8-core:
|
|||||||
image: python:3.8-buster
|
image: python:3.8-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py38-core
|
- tox -e py38-core
|
||||||
before_script:
|
|
||||||
- apt-get update && apt-get install redis-server -y
|
|
||||||
- redis-server --daemonize yes
|
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
|
||||||
- pip install wheel tox
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@ -53,12 +47,6 @@ test-3.9-core:
|
|||||||
image: python:3.9-buster
|
image: python:3.9-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py39-core
|
- tox -e py39-core
|
||||||
before_script:
|
|
||||||
- apt-get update && apt-get install redis-server -y
|
|
||||||
- redis-server --daemonize yes
|
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
|
||||||
- pip install wheel tox
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@ -68,12 +56,6 @@ test-3.7-all:
|
|||||||
image: python:3.7-buster
|
image: python:3.7-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py37-all
|
- tox -e py37-all
|
||||||
before_script:
|
|
||||||
- apt-get update && apt-get install redis-server -y
|
|
||||||
- redis-server --daemonize yes
|
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
|
||||||
- pip install wheel tox
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@ -83,12 +65,6 @@ test-3.8-all:
|
|||||||
image: python:3.8-buster
|
image: python:3.8-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py38-all
|
- tox -e py38-all
|
||||||
before_script:
|
|
||||||
- apt-get update && apt-get install redis-server -y
|
|
||||||
- redis-server --daemonize yes
|
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
|
||||||
- pip install wheel tox
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@ -98,12 +74,6 @@ test-3.9-all:
|
|||||||
image: python:3.9-buster
|
image: python:3.9-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py39-all
|
- tox -e py39-all
|
||||||
before_script:
|
|
||||||
- apt-get update && apt-get install redis-server -y
|
|
||||||
- redis-server --daemonize yes
|
|
||||||
- redis-cli ping
|
|
||||||
- python -V
|
|
||||||
- pip install wheel tox
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||||
from django.contrib.auth.models import User as BaseUser, \
|
from django.contrib.auth.models import User as BaseUser, \
|
||||||
Permission as BasePermission, Group
|
Permission as BasePermission, Group
|
||||||
from django.db.models import Q, F
|
from django.db.models import Count, Q
|
||||||
from allianceauth.services.hooks import ServicesHook
|
from allianceauth.services.hooks import ServicesHook
|
||||||
from django.db.models.signals import pre_save, post_save, pre_delete, \
|
from django.db.models.signals import pre_save, post_save, pre_delete, \
|
||||||
post_delete, m2m_changed
|
post_delete, m2m_changed
|
||||||
@ -24,11 +22,6 @@ from allianceauth.eveonline.tasks import update_character
|
|||||||
from .app_settings import AUTHENTICATION_ADMIN_USERS_MAX_GROUPS, \
|
from .app_settings import AUTHENTICATION_ADMIN_USERS_MAX_GROUPS, \
|
||||||
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
|
||||||
_has_auto_groups = True
|
|
||||||
else:
|
|
||||||
_has_auto_groups = False
|
|
||||||
|
|
||||||
|
|
||||||
def make_service_hooks_update_groups_action(service):
|
def make_service_hooks_update_groups_action(service):
|
||||||
"""
|
"""
|
||||||
@ -92,7 +85,6 @@ class UserProfileInline(admin.StackedInline):
|
|||||||
query |= Q(userprofile__isnull=True)
|
query |= Q(userprofile__isnull=True)
|
||||||
else:
|
else:
|
||||||
query |= Q(character_ownership__user=obj)
|
query |= Q(character_ownership__user=obj)
|
||||||
qs = EveCharacter.objects.filter(query)
|
|
||||||
formset = super().get_formset(request, obj=obj, **kwargs)
|
formset = super().get_formset(request, obj=obj, **kwargs)
|
||||||
|
|
||||||
def get_kwargs(self, index):
|
def get_kwargs(self, index):
|
||||||
@ -121,6 +113,8 @@ def user_profile_pic(obj):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
user_profile_pic.short_description = ''
|
user_profile_pic.short_description = ''
|
||||||
|
|
||||||
|
|
||||||
@ -152,6 +146,7 @@ def user_username(obj):
|
|||||||
user_obj.username,
|
user_obj.username,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
user_username.short_description = 'user / main'
|
user_username.short_description = 'user / main'
|
||||||
user_username.admin_order_field = 'username'
|
user_username.admin_order_field = 'username'
|
||||||
|
|
||||||
@ -168,7 +163,8 @@ def user_main_organization(obj):
|
|||||||
else:
|
else:
|
||||||
corporation = user_obj.profile.main_character.corporation_name
|
corporation = user_obj.profile.main_character.corporation_name
|
||||||
if user_obj.profile.main_character.alliance_id:
|
if user_obj.profile.main_character.alliance_id:
|
||||||
result = format_html('{}<br>{}',
|
result = format_html(
|
||||||
|
'{}<br>{}',
|
||||||
corporation,
|
corporation,
|
||||||
user_obj.profile.main_character.alliance_name
|
user_obj.profile.main_character.alliance_name
|
||||||
)
|
)
|
||||||
@ -176,6 +172,7 @@ def user_main_organization(obj):
|
|||||||
result = corporation
|
result = corporation
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
user_main_organization.short_description = 'Corporation / Alliance (Main)'
|
user_main_organization.short_description = 'Corporation / Alliance (Main)'
|
||||||
user_main_organization.admin_order_field = \
|
user_main_organization.admin_order_field = \
|
||||||
'profile__main_character__corporation_name'
|
'profile__main_character__corporation_name'
|
||||||
@ -205,13 +202,13 @@ class MainCorporationsFilter(admin.SimpleListFilter):
|
|||||||
return qs.all()
|
return qs.all()
|
||||||
else:
|
else:
|
||||||
if qs.model == User:
|
if qs.model == User:
|
||||||
return qs\
|
return qs.filter(
|
||||||
.filter(profile__main_character__corporation_id=\
|
profile__main_character__corporation_id=self.value()
|
||||||
self.value())
|
)
|
||||||
else:
|
else:
|
||||||
return qs\
|
return qs.filter(
|
||||||
.filter(user__profile__main_character__corporation_id=\
|
user__profile__main_character__corporation_id=self.value()
|
||||||
self.value())
|
)
|
||||||
|
|
||||||
|
|
||||||
class MainAllianceFilter(admin.SimpleListFilter):
|
class MainAllianceFilter(admin.SimpleListFilter):
|
||||||
@ -239,12 +236,11 @@ class MainAllianceFilter(admin.SimpleListFilter):
|
|||||||
return qs.all()
|
return qs.all()
|
||||||
else:
|
else:
|
||||||
if qs.model == User:
|
if qs.model == User:
|
||||||
return qs\
|
return qs.filter(profile__main_character__alliance_id=self.value())
|
||||||
.filter(profile__main_character__alliance_id=self.value())
|
|
||||||
else:
|
else:
|
||||||
return qs\
|
return qs.filter(
|
||||||
.filter(user__profile__main_character__alliance_id=\
|
user__profile__main_character__alliance_id=self.value()
|
||||||
self.value())
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_main_character_model(modeladmin, request, queryset):
|
def update_main_character_model(modeladmin, request, queryset):
|
||||||
@ -259,6 +255,7 @@ def update_main_character_model(modeladmin, request, queryset):
|
|||||||
'Update from ESI started for {} characters'.format(tasks_count)
|
'Update from ESI started for {} characters'.format(tasks_count)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
update_main_character_model.short_description = \
|
update_main_character_model.short_description = \
|
||||||
'Update main character model from ESI'
|
'Update main character model from ESI'
|
||||||
|
|
||||||
@ -267,7 +264,6 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
"""Extending Django's UserAdmin model
|
"""Extending Django's UserAdmin model
|
||||||
|
|
||||||
Behavior of groups and characters columns can be configured via settings
|
Behavior of groups and characters columns can be configured via settings
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
@ -275,24 +271,9 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
"all": ("authentication/css/admin.css",)
|
"all": ("authentication/css/admin.css",)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealGroupsFilter(admin.SimpleListFilter):
|
def get_queryset(self, request):
|
||||||
"""Custom filter to get groups w/o Autogroups"""
|
qs = super().get_queryset(request)
|
||||||
title = 'group'
|
return qs.prefetch_related("character_ownerships__character", "groups")
|
||||||
parameter_name = 'group_id__exact'
|
|
||||||
|
|
||||||
def lookups(self, request, model_admin):
|
|
||||||
qs = Group.objects.all().order_by(Lower('name'))
|
|
||||||
if _has_auto_groups:
|
|
||||||
qs = qs\
|
|
||||||
.filter(managedalliancegroup__isnull=True)\
|
|
||||||
.filter(managedcorpgroup__isnull=True)
|
|
||||||
return tuple([(x.pk, x.name) for x in qs])
|
|
||||||
|
|
||||||
def queryset(self, request, queryset):
|
|
||||||
if self.value() is None:
|
|
||||||
return queryset.all()
|
|
||||||
else:
|
|
||||||
return queryset.filter(groups__pk=self.value())
|
|
||||||
|
|
||||||
def get_actions(self, request):
|
def get_actions(self, request):
|
||||||
actions = super(BaseUserAdmin, self).get_actions(request)
|
actions = super(BaseUserAdmin, self).get_actions(request)
|
||||||
@ -341,11 +322,9 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
inlines = BaseUserAdmin.inlines + [UserProfileInline]
|
inlines = BaseUserAdmin.inlines + [UserProfileInline]
|
||||||
|
|
||||||
ordering = ('username', )
|
ordering = ('username', )
|
||||||
list_select_related = True
|
list_select_related = ('profile__state', 'profile__main_character')
|
||||||
show_full_result_count = True
|
show_full_result_count = True
|
||||||
|
|
||||||
list_display = (
|
list_display = (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
@ -358,10 +337,9 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
'_role'
|
'_role'
|
||||||
)
|
)
|
||||||
list_display_links = None
|
list_display_links = None
|
||||||
|
|
||||||
list_filter = (
|
list_filter = (
|
||||||
'profile__state',
|
'profile__state',
|
||||||
RealGroupsFilter,
|
'groups',
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
'is_active',
|
'is_active',
|
||||||
@ -375,21 +353,15 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _characters(self, obj):
|
def _characters(self, obj):
|
||||||
my_characters = [
|
character_ownerships = list(obj.character_ownerships.all())
|
||||||
x.character.character_name
|
characters = [obj.character.character_name for obj in character_ownerships]
|
||||||
for x in CharacterOwnership.objects\
|
|
||||||
.filter(user=obj)\
|
|
||||||
.order_by('character__character_name')\
|
|
||||||
.select_related()
|
|
||||||
]
|
|
||||||
return self._list_2_html_w_tooltips(
|
return self._list_2_html_w_tooltips(
|
||||||
my_characters,
|
sorted(characters),
|
||||||
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
||||||
)
|
)
|
||||||
|
|
||||||
_characters.short_description = 'characters'
|
_characters.short_description = 'characters'
|
||||||
|
|
||||||
|
|
||||||
def _state(self, obj):
|
def _state(self, obj):
|
||||||
return obj.profile.state.name
|
return obj.profile.state.name
|
||||||
|
|
||||||
@ -397,19 +369,9 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
_state.admin_order_field = 'profile__state'
|
_state.admin_order_field = 'profile__state'
|
||||||
|
|
||||||
def _groups(self, obj):
|
def _groups(self, obj):
|
||||||
if not _has_auto_groups:
|
my_groups = sorted([group.name for group in list(obj.groups.all())])
|
||||||
my_groups = [x.name for x in obj.groups.order_by('name')]
|
|
||||||
else:
|
|
||||||
my_groups = [
|
|
||||||
x.name for x in obj.groups\
|
|
||||||
.filter(managedalliancegroup__isnull=True)\
|
|
||||||
.filter(managedcorpgroup__isnull=True)\
|
|
||||||
.order_by('name')
|
|
||||||
]
|
|
||||||
|
|
||||||
return self._list_2_html_w_tooltips(
|
return self._list_2_html_w_tooltips(
|
||||||
my_groups,
|
my_groups, AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
||||||
AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_groups.short_description = 'groups'
|
_groups.short_description = 'groups'
|
||||||
@ -446,9 +408,14 @@ class StateAdmin(admin.ModelAdmin):
|
|||||||
list_select_related = True
|
list_select_related = True
|
||||||
list_display = ('name', 'priority', '_user_count')
|
list_display = ('name', 'priority', '_user_count')
|
||||||
|
|
||||||
|
def get_queryset(self, request):
|
||||||
|
qs = super().get_queryset(request)
|
||||||
|
return qs.annotate(user_count=Count("userprofile__id"))
|
||||||
|
|
||||||
def _user_count(self, obj):
|
def _user_count(self, obj):
|
||||||
return obj.userprofile_set.all().count()
|
return obj.user_count
|
||||||
_user_count.short_description = 'Users'
|
_user_count.short_description = 'Users'
|
||||||
|
_user_count.admin_order_field = 'user_count'
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
@ -504,7 +471,8 @@ class BaseOwnershipAdmin(admin.ModelAdmin):
|
|||||||
"all": ("authentication/css/admin.css",)
|
"all": ("authentication/css/admin.css",)
|
||||||
}
|
}
|
||||||
|
|
||||||
list_select_related = True
|
list_select_related = (
|
||||||
|
'user__profile__state', 'user__profile__main_character', 'character')
|
||||||
list_display = (
|
list_display = (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
@ -542,6 +510,7 @@ class CharacterOwnershipAdmin(BaseOwnershipAdmin):
|
|||||||
class PermissionAdmin(admin.ModelAdmin):
|
class PermissionAdmin(admin.ModelAdmin):
|
||||||
actions = None
|
actions = None
|
||||||
readonly_fields = [field.name for field in BasePermission._meta.fields]
|
readonly_fields = [field.name for field in BasePermission._meta.fields]
|
||||||
|
search_fields = ('codename', )
|
||||||
list_display = ('admin_name', 'name', 'codename', 'content_type')
|
list_display = ('admin_name', 'name', 'codename', 'content_type')
|
||||||
list_filter = ('content_type__app_label',)
|
list_filter = ('content_type__app_label',)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ def get_admin_change_view_url(obj: object) -> str:
|
|||||||
args=(obj.pk,)
|
args=(obj.pk,)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_admin_search_url(ModelClass: type) -> str:
|
def get_admin_search_url(ModelClass: type) -> str:
|
||||||
"""returns URL to search URL for model of given object"""
|
"""returns URL to search URL for model of given object"""
|
||||||
return '{}{}/'.format(
|
return '{}{}/'.format(
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
from unittest.mock import patch, MagicMock
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from django.contrib.auth.models import User as BaseUser, Group
|
from django.contrib.auth.models import Group
|
||||||
from django.test import TestCase, RequestFactory, Client
|
from django.test import TestCase, RequestFactory, Client
|
||||||
|
|
||||||
from allianceauth.authentication.models import (
|
from allianceauth.authentication.models import (
|
||||||
@ -19,7 +17,6 @@ from allianceauth.tests.auth_utils import AuthUtils
|
|||||||
from ..admin import (
|
from ..admin import (
|
||||||
BaseUserAdmin,
|
BaseUserAdmin,
|
||||||
CharacterOwnershipAdmin,
|
CharacterOwnershipAdmin,
|
||||||
PermissionAdmin,
|
|
||||||
StateAdmin,
|
StateAdmin,
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
@ -35,11 +32,6 @@ from ..admin import (
|
|||||||
)
|
)
|
||||||
from . import get_admin_change_view_url, get_admin_search_url
|
from . import get_admin_change_view_url, get_admin_search_url
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
|
||||||
_has_auto_groups = True
|
|
||||||
from allianceauth.eveonline.autogroups.models import AutogroupsConfig
|
|
||||||
else:
|
|
||||||
_has_auto_groups = False
|
|
||||||
|
|
||||||
MODULE_PATH = 'allianceauth.authentication.admin'
|
MODULE_PATH = 'allianceauth.authentication.admin'
|
||||||
|
|
||||||
@ -48,6 +40,7 @@ class MockRequest(object):
|
|||||||
def __init__(self, user=None):
|
def __init__(self, user=None):
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
|
|
||||||
class TestCaseWithTestData(TestCase):
|
class TestCaseWithTestData(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -279,6 +272,7 @@ class TestStateAdmin(TestCaseWithTestData):
|
|||||||
expected = 200
|
expected = 200
|
||||||
self.assertEqual(response.status_code, expected)
|
self.assertEqual(response.status_code, expected)
|
||||||
|
|
||||||
|
|
||||||
class TestUserAdmin(TestCaseWithTestData):
|
class TestUserAdmin(TestCaseWithTestData):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -288,23 +282,11 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
)
|
)
|
||||||
self.character_1 = self.user_1.character_ownerships.first().character
|
self.character_1 = self.user_1.character_ownerships.first().character
|
||||||
|
|
||||||
def _create_autogroups(self):
|
|
||||||
"""create autogroups for corps and alliances"""
|
|
||||||
if _has_auto_groups:
|
|
||||||
autogroups_config = AutogroupsConfig(
|
|
||||||
corp_groups = True,
|
|
||||||
alliance_groups = True
|
|
||||||
)
|
|
||||||
autogroups_config.save()
|
|
||||||
for state in State.objects.all():
|
|
||||||
autogroups_config.states.add(state)
|
|
||||||
autogroups_config.update_corp_group_membership(self.user_1)
|
|
||||||
|
|
||||||
# column rendering
|
|
||||||
|
|
||||||
def test_user_profile_pic_u1(self):
|
def test_user_profile_pic_u1(self):
|
||||||
expected = ('<img src="https://images.evetech.net/characters/1001/'
|
expected = (
|
||||||
'portrait?size=32" class="img-circle">')
|
'<img src="https://images.evetech.net/characters/1001/'
|
||||||
|
'portrait?size=32" class="img-circle">'
|
||||||
|
)
|
||||||
self.assertEqual(user_profile_pic(self.user_1), expected)
|
self.assertEqual(user_profile_pic(self.user_1), expected)
|
||||||
|
|
||||||
def test_user_profile_pic_u3(self):
|
def test_user_profile_pic_u3(self):
|
||||||
@ -352,36 +334,16 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_groups_u1(self):
|
def test_groups_u1(self):
|
||||||
self._create_autogroups()
|
|
||||||
expected = 'Group 1'
|
expected = 'Group 1'
|
||||||
result = self.modeladmin._groups(self.user_1)
|
result = self.modeladmin._groups(self.user_1)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_groups_u2(self):
|
def test_groups_u2(self):
|
||||||
self._create_autogroups()
|
|
||||||
expected = 'Group 2'
|
expected = 'Group 2'
|
||||||
result = self.modeladmin._groups(self.user_2)
|
result = self.modeladmin._groups(self.user_2)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_groups_u3(self):
|
def test_groups_u3(self):
|
||||||
self._create_autogroups()
|
|
||||||
result = self.modeladmin._groups(self.user_3)
|
|
||||||
self.assertIsNone(result)
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_groups_u1_no_autogroups(self):
|
|
||||||
expected = 'Group 1'
|
|
||||||
result = self.modeladmin._groups(self.user_1)
|
|
||||||
self.assertEqual(result, expected)
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_groups_u2_no_autogroups(self):
|
|
||||||
expected = 'Group 2'
|
|
||||||
result = self.modeladmin._groups(self.user_2)
|
|
||||||
self.assertEqual(result, expected)
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_groups_u3_no_autogroups(self):
|
|
||||||
result = self.modeladmin._groups(self.user_3)
|
result = self.modeladmin._groups(self.user_3)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
@ -413,8 +375,10 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
|
|
||||||
def test_list_2_html_w_tooltips_w_cutoff(self):
|
def test_list_2_html_w_tooltips_w_cutoff(self):
|
||||||
items = ['one', 'two', 'three']
|
items = ['one', 'two', 'three']
|
||||||
expected = ('<span data-tooltip="one, two, three" '
|
expected = (
|
||||||
'class="tooltip">one, two, (...)</span>')
|
'<span data-tooltip="one, two, three" '
|
||||||
|
'class="tooltip">one, two, (...)</span>'
|
||||||
|
)
|
||||||
result = self.modeladmin._list_2_html_w_tooltips(items, 2)
|
result = self.modeladmin._list_2_html_w_tooltips(items, 2)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
@ -440,62 +404,6 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
|
|
||||||
# filters
|
# filters
|
||||||
|
|
||||||
def test_filter_real_groups_with_autogroups(self):
|
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
|
||||||
list_filter = (UserAdmin.RealGroupsFilter,)
|
|
||||||
|
|
||||||
self._create_autogroups()
|
|
||||||
my_modeladmin = UserAdminTest(User, AdminSite())
|
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
|
||||||
request = self.factory.get('/')
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
filters = changelist.get_filters(request)
|
|
||||||
filterspec = filters[0][0]
|
|
||||||
expected = [
|
|
||||||
(self.group_1.pk, self.group_1.name),
|
|
||||||
(self.group_2.pk, self.group_2.name),
|
|
||||||
]
|
|
||||||
self.assertEqual(filterspec.lookup_choices, expected)
|
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
|
||||||
request = self.factory.get('/', {'group_id__exact': self.group_1.pk})
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
queryset = changelist.get_queryset(request)
|
|
||||||
expected = User.objects.filter(groups__in=[self.group_1])
|
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_filter_real_groups_no_autogroups(self):
|
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
|
||||||
list_filter = (UserAdmin.RealGroupsFilter,)
|
|
||||||
|
|
||||||
my_modeladmin = UserAdminTest(User, AdminSite())
|
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
|
||||||
request = self.factory.get('/')
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
filters = changelist.get_filters(request)
|
|
||||||
filterspec = filters[0][0]
|
|
||||||
expected = [
|
|
||||||
(self.group_1.pk, self.group_1.name),
|
|
||||||
(self.group_2.pk, self.group_2.name),
|
|
||||||
]
|
|
||||||
self.assertEqual(filterspec.lookup_choices, expected)
|
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
|
||||||
request = self.factory.get('/', {'group_id__exact': self.group_1.pk})
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
queryset = changelist.get_queryset(request)
|
|
||||||
expected = User.objects.filter(groups__in=[self.group_1])
|
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
|
||||||
|
|
||||||
def test_filter_main_corporations(self):
|
def test_filter_main_corporations(self):
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
class UserAdminTest(BaseUserAdmin):
|
||||||
@ -603,7 +511,6 @@ class TestMakeServicesHooksActions(TestCaseWithTestData):
|
|||||||
def sync_nicknames_bulk(self, user):
|
def sync_nicknames_bulk(self, user):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_service_has_update_groups_only(self):
|
def test_service_has_update_groups_only(self):
|
||||||
service = self.MyServicesHookTypeA()
|
service = self.MyServicesHookTypeA()
|
||||||
mock_service = MagicMock(spec=service)
|
mock_service = MagicMock(spec=service)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from math import ceil
|
from math import ceil
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from requests import RequestException
|
|
||||||
import requests_mock
|
import requests_mock
|
||||||
from packaging.version import Version as Pep440Version
|
from packaging.version import Version as Pep440Version
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from allianceauth.templatetags.admin_status import (
|
from allianceauth.templatetags.admin_status import (
|
||||||
@ -13,7 +13,6 @@ from allianceauth.templatetags.admin_status import (
|
|||||||
_current_notifications,
|
_current_notifications,
|
||||||
_current_version_summary,
|
_current_version_summary,
|
||||||
_fetch_notification_issues_from_gitlab,
|
_fetch_notification_issues_from_gitlab,
|
||||||
_fetch_tags_from_gitlab,
|
|
||||||
_latests_versions
|
_latests_versions
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,35 +102,51 @@ class TestStatusOverviewTag(TestCase):
|
|||||||
|
|
||||||
class TestNotifications(TestCase):
|
class TestNotifications(TestCase):
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
cache.clear()
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_fetch_notification_issues_from_gitlab(self, requests_mocker):
|
def test_fetch_notification_issues_from_gitlab(self, requests_mocker):
|
||||||
|
# given
|
||||||
url = (
|
url = (
|
||||||
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
||||||
'?labels=announcement'
|
'?labels=announcement'
|
||||||
)
|
)
|
||||||
requests_mocker.get(url, json=GITHUB_NOTIFICATION_ISSUES)
|
requests_mocker.get(url, json=GITHUB_NOTIFICATION_ISSUES)
|
||||||
|
# when
|
||||||
result = _fetch_notification_issues_from_gitlab()
|
result = _fetch_notification_issues_from_gitlab()
|
||||||
|
# then
|
||||||
self.assertEqual(result, GITHUB_NOTIFICATION_ISSUES)
|
self.assertEqual(result, GITHUB_NOTIFICATION_ISSUES)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_notifications_normal(self, mock_cache):
|
def test_current_notifications_normal(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = GITHUB_NOTIFICATION_ISSUES
|
mock_cache.get_or_set.return_value = GITHUB_NOTIFICATION_ISSUES
|
||||||
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
|
# then
|
||||||
self.assertEqual(result['notifications'], GITHUB_NOTIFICATION_ISSUES[:5])
|
self.assertEqual(result['notifications'], GITHUB_NOTIFICATION_ISSUES[:5])
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@requests_mock.mock()
|
||||||
def test_current_notifications_failed(self, mock_cache):
|
def test_current_notifications_failed(self, requests_mocker):
|
||||||
mock_cache.get_or_set.side_effect = RequestException
|
# given
|
||||||
|
url = (
|
||||||
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
||||||
|
'?labels=announcement'
|
||||||
|
)
|
||||||
|
requests_mocker.get(url, status_code=404)
|
||||||
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
|
# then
|
||||||
self.assertEqual(result['notifications'], list())
|
self.assertEqual(result['notifications'], list())
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_notifications_is_none(self, mock_cache):
|
def test_current_notifications_is_none(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = None
|
mock_cache.get_or_set.return_value = None
|
||||||
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
|
# then
|
||||||
self.assertEqual(result['notifications'], list())
|
self.assertEqual(result['notifications'], list())
|
||||||
|
|
||||||
|
|
||||||
@ -143,12 +158,17 @@ class TestCeleryQueueLength(TestCase):
|
|||||||
|
|
||||||
class TestVersionTags(TestCase):
|
class TestVersionTags(TestCase):
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
cache.clear()
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_version_info_normal(self, mock_cache):
|
def test_current_version_info_normal(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = GITHUB_TAGS
|
mock_cache.get_or_set.return_value = GITHUB_TAGS
|
||||||
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
|
# then
|
||||||
self.assertTrue(result['latest_major'])
|
self.assertTrue(result['latest_major'])
|
||||||
self.assertTrue(result['latest_minor'])
|
self.assertTrue(result['latest_minor'])
|
||||||
self.assertTrue(result['latest_patch'])
|
self.assertTrue(result['latest_patch'])
|
||||||
@ -158,32 +178,41 @@ class TestVersionTags(TestCase):
|
|||||||
self.assertEqual(result['latest_beta_version'], '2.4.6a1')
|
self.assertEqual(result['latest_beta_version'], '2.4.6a1')
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@requests_mock.mock()
|
||||||
def test_current_version_info_failed(self, mock_cache):
|
def test_current_version_info_failed(self, requests_mocker):
|
||||||
mock_cache.get_or_set.side_effect = RequestException
|
# given
|
||||||
|
url = (
|
||||||
expected = {}
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
||||||
|
'/repository/tags'
|
||||||
|
)
|
||||||
|
requests_mocker.get(url, status_code=500)
|
||||||
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
self.assertEqual(result, expected)
|
# then
|
||||||
|
self.assertEqual(result, {})
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_fetch_tags_from_gitlab(self, requests_mocker):
|
def test_fetch_tags_from_gitlab(self, requests_mocker):
|
||||||
|
# given
|
||||||
url = (
|
url = (
|
||||||
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
||||||
'/repository/tags'
|
'/repository/tags'
|
||||||
)
|
)
|
||||||
requests_mocker.get(url, json=GITHUB_TAGS)
|
requests_mocker.get(url, json=GITHUB_TAGS)
|
||||||
result = _fetch_tags_from_gitlab()
|
# when
|
||||||
self.assertEqual(result, GITHUB_TAGS)
|
result = _current_version_summary()
|
||||||
|
# then
|
||||||
|
self.assertTrue(result)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_version_info_return_no_data(self, mock_cache):
|
def test_current_version_info_return_no_data(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = None
|
mock_cache.get_or_set.return_value = None
|
||||||
|
# when
|
||||||
expected = {}
|
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
self.assertEqual(result, expected)
|
# then
|
||||||
|
self.assertEqual(result, {})
|
||||||
|
|
||||||
|
|
||||||
class TestLatestsVersion(TestCase):
|
class TestLatestsVersion(TestCase):
|
||||||
|
@ -96,24 +96,62 @@ class EveAllianceForm(EveEntityForm):
|
|||||||
|
|
||||||
@admin.register(EveCorporationInfo)
|
@admin.register(EveCorporationInfo)
|
||||||
class EveCorporationInfoAdmin(admin.ModelAdmin):
|
class EveCorporationInfoAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ['corporation_name']
|
||||||
|
list_display = ('corporation_name', 'alliance')
|
||||||
|
list_select_related = ('alliance',)
|
||||||
|
list_filter = (('alliance', admin.RelatedOnlyFieldListFilter),)
|
||||||
|
ordering = ('corporation_name',)
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
if not obj or not obj.pk:
|
if not obj or not obj.pk:
|
||||||
return EveCorporationForm
|
return EveCorporationForm
|
||||||
return super(EveCorporationInfoAdmin, self).get_form(request, obj=obj, **kwargs)
|
return super().get_form(request, obj=obj, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(EveAllianceInfo)
|
@admin.register(EveAllianceInfo)
|
||||||
class EveAllianceInfoAdmin(admin.ModelAdmin):
|
class EveAllianceInfoAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ['alliance_name']
|
||||||
|
list_display = ('alliance_name',)
|
||||||
|
ordering = ('alliance_name',)
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
if not obj or not obj.pk:
|
if not obj or not obj.pk:
|
||||||
return EveAllianceForm
|
return EveAllianceForm
|
||||||
return super(EveAllianceInfoAdmin, self).get_form(request, obj=obj, **kwargs)
|
return super().get_form(request, obj=obj, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(EveCharacter)
|
@admin.register(EveCharacter)
|
||||||
class EveCharacterAdmin(admin.ModelAdmin):
|
class EveCharacterAdmin(admin.ModelAdmin):
|
||||||
search_fields = ['character_name', 'corporation_name', 'alliance_name', 'character_ownership__user__username']
|
search_fields = [
|
||||||
list_display = ('character_name', 'corporation_name', 'alliance_name', 'user', 'main_character')
|
'character_name',
|
||||||
|
'corporation_name',
|
||||||
|
'alliance_name',
|
||||||
|
'character_ownership__user__username'
|
||||||
|
]
|
||||||
|
list_display = (
|
||||||
|
'character_name', 'corporation_name', 'alliance_name', 'user', 'main_character'
|
||||||
|
)
|
||||||
|
list_select_related = (
|
||||||
|
'character_ownership', 'character_ownership__user__profile__main_character'
|
||||||
|
)
|
||||||
|
list_filter = (
|
||||||
|
'corporation_name',
|
||||||
|
'alliance_name',
|
||||||
|
(
|
||||||
|
'character_ownership__user__profile__main_character',
|
||||||
|
admin.RelatedOnlyFieldListFilter
|
||||||
|
),
|
||||||
|
)
|
||||||
|
ordering = ('character_name', )
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def user(obj):
|
def user(obj):
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django.conf import settings
|
from django.apps import apps
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.models import Group as BaseGroup, User
|
from django.contrib.auth.models import Group as BaseGroup, User
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
@ -10,9 +9,8 @@ from django.dispatch import receiver
|
|||||||
|
|
||||||
from .models import AuthGroup
|
from .models import AuthGroup
|
||||||
from .models import GroupRequest
|
from .models import GroupRequest
|
||||||
from . import signals
|
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
if 'eve_autogroups' in apps.app_configs:
|
||||||
_has_auto_groups = True
|
_has_auto_groups = True
|
||||||
else:
|
else:
|
||||||
_has_auto_groups = False
|
_has_auto_groups = False
|
||||||
@ -97,9 +95,10 @@ class HasLeaderFilter(admin.SimpleListFilter):
|
|||||||
else:
|
else:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class GroupAdmin(admin.ModelAdmin):
|
class GroupAdmin(admin.ModelAdmin):
|
||||||
list_select_related = True
|
list_select_related = ('authgroup',)
|
||||||
ordering = ('name', )
|
ordering = ('name',)
|
||||||
list_display = (
|
list_display = (
|
||||||
'name',
|
'name',
|
||||||
'_description',
|
'_description',
|
||||||
@ -121,6 +120,9 @@ 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.prefetch_related('managedalliancegroup_set', 'managedcorpgroup_set')
|
||||||
|
qs = qs.prefetch_related('authgroup__group_leaders')
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
member_count=Count('user', distinct=True),
|
member_count=Count('user', distinct=True),
|
||||||
)
|
)
|
||||||
@ -173,13 +175,29 @@ class Group(BaseGroup):
|
|||||||
verbose_name = BaseGroup._meta.verbose_name
|
verbose_name = BaseGroup._meta.verbose_name
|
||||||
verbose_name_plural = BaseGroup._meta.verbose_name_plural
|
verbose_name_plural = BaseGroup._meta.verbose_name_plural
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
admin.site.unregister(BaseGroup)
|
admin.site.unregister(BaseGroup)
|
||||||
finally:
|
finally:
|
||||||
admin.site.register(Group, GroupAdmin)
|
admin.site.register(Group, GroupAdmin)
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(GroupRequest)
|
@admin.register(GroupRequest)
|
||||||
|
class GroupRequestAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ('user__username', )
|
||||||
|
list_display = ('id', 'group', 'user', '_leave_request', 'status')
|
||||||
|
list_filter = (
|
||||||
|
('group', admin.RelatedOnlyFieldListFilter),
|
||||||
|
('user', admin.RelatedOnlyFieldListFilter),
|
||||||
|
'leave_request',
|
||||||
|
'status'
|
||||||
|
)
|
||||||
|
|
||||||
|
def _leave_request(self, obj) -> True:
|
||||||
|
return obj.leave_request
|
||||||
|
|
||||||
|
_leave_request.short_description = 'is leave request'
|
||||||
|
_leave_request.boolean = True
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_save, sender=Group)
|
@receiver(pre_save, sender=Group)
|
||||||
|
@ -5,3 +5,6 @@ class GroupManagementConfig(AppConfig):
|
|||||||
name = 'allianceauth.groupmanagement'
|
name = 'allianceauth.groupmanagement'
|
||||||
label = 'groupmanagement'
|
label = 'groupmanagement'
|
||||||
verbose_name = 'Group Management'
|
verbose_name = 'Group Management'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
from . import signals # noqa: F401
|
||||||
|
@ -40,9 +40,11 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="panel panel-default panel-tabs-aa">
|
||||||
<div id="add" class="tab-pane fade in active panel panel-default">
|
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
<div class="tab-content">
|
||||||
|
|
||||||
|
<div id="add" class="tab-pane active">
|
||||||
{% if acceptrequests %}
|
{% if acceptrequests %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-aa">
|
<table class="table table-aa">
|
||||||
@ -97,10 +99,8 @@
|
|||||||
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
|
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="leave" class="tab-pane fade panel panel-default">
|
<div id="leave" class="tab-pane">
|
||||||
<div class="panel-body">
|
|
||||||
{% if leaverequests %}
|
{% if leaverequests %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-aa">
|
<table class="table table-aa">
|
||||||
@ -158,4 +158,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 3.1.6 on 2021-03-23 13:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mumble', '0001_squashed_0011_auto_20201011_1009'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='last_connect',
|
||||||
|
field=models.DateTimeField(blank=True, editable=False, help_text='Timestamp of the users Last Connection to Mumble', max_length=254, null=True, verbose_name='Last Connection'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='last_disconnect',
|
||||||
|
field=models.DateTimeField(blank=True, editable=False, help_text='Timestamp of the users Last Disconnection to Mumble', max_length=254, null=True, verbose_name='Last Disconnection'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='release',
|
||||||
|
field=models.TextField(blank=True, editable=False, help_text='The Mumble Release the user last authenticated with', max_length=254, null=True, verbose_name='Mumble Release'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='version',
|
||||||
|
field=models.IntegerField(blank=True, editable=False, help_text='Client version. Major version in upper 16 bits, followed by 8 bits of minor version and 8 bits of patchlevel. Version 1.2.3 = 0x010203.', null=True, verbose_name='Mumble Version'),
|
||||||
|
),
|
||||||
|
]
|
@ -74,7 +74,41 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
editable=False,
|
editable=False,
|
||||||
help_text="Hash of Mumble client certificate as presented when user authenticates"
|
help_text="Hash of Mumble client certificate as presented when user authenticates"
|
||||||
)
|
)
|
||||||
display_name = models.CharField(max_length=254, unique=True)
|
display_name = models.CharField(
|
||||||
|
max_length=254,
|
||||||
|
unique=True
|
||||||
|
)
|
||||||
|
release = models.TextField(
|
||||||
|
verbose_name="Mumble Release",
|
||||||
|
max_length=254,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="The Mumble Release the user last authenticated with"
|
||||||
|
)
|
||||||
|
version = models.IntegerField(
|
||||||
|
verbose_name="Mumble Version",
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="Client version. Major version in upper 16 bits, followed by 8 bits of minor version and 8 bits of patchlevel. Version 1.2.3 = 0x010203."
|
||||||
|
)
|
||||||
|
last_connect = models.DateTimeField(
|
||||||
|
verbose_name="Last Connection",
|
||||||
|
max_length=254,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="Timestamp of the users Last Connection to Mumble"
|
||||||
|
)
|
||||||
|
last_disconnect = models.DateTimeField(
|
||||||
|
verbose_name="Last Disconnection",
|
||||||
|
max_length=254,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="Timestamp of the users Last Disconnection to Mumble"
|
||||||
|
)
|
||||||
|
|
||||||
objects = MumbleManager()
|
objects = MumbleManager()
|
||||||
|
|
||||||
|
@ -43,27 +43,51 @@ ul.list-group.list-group-horizontal > li.list-group-item {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* style group headers within a table */
|
@media all {
|
||||||
.tr-group {
|
/* style nav tabs in dark mode*/
|
||||||
|
.template-dark-mode .nav-tabs > li.active > a {
|
||||||
|
background-color: rgb(70, 69, 69)!important;
|
||||||
|
color: rgb(255, 255, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-tabs-aa {
|
||||||
|
border-top: none;
|
||||||
|
border-top-left-radius: 0%;
|
||||||
|
border-top-right-radius: 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* style group headers within a table */
|
||||||
|
.template-light-mode .tr-group {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
background-color: #e6e6e6 !important;
|
background-color: #e6e6e6 !important;
|
||||||
}
|
}
|
||||||
|
.template-dark-mode .tr-group {
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: rgb(105, 105, 105) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* default style for tables */
|
/* default style for tables */
|
||||||
.table-aa > thead > tr > th{
|
.template-light-mode .table-aa > thead > tr > th{
|
||||||
border-bottom: 1px solid #f2f2f2;
|
border-bottom: 1px solid #f2f2f2;
|
||||||
}
|
}
|
||||||
.table-aa > thead > tr > th{
|
.template-dark-mode .table-aa > thead > tr > th{
|
||||||
|
border-bottom: 1px solid rgb(70, 69, 69);
|
||||||
|
}
|
||||||
|
.table-aa > thead > tr > th{
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.table-aa > tbody > tr > td{
|
.template-light-mode .table-aa > tbody > tr > td{
|
||||||
border-bottom: 1px solid #f2f2f2;
|
border-bottom: 1px solid #f2f2f2;
|
||||||
}
|
}
|
||||||
.table-aa > tbody > tr > td {
|
.template-dark-mode .table-aa > tbody > tr > td{
|
||||||
|
border-bottom: 1px solid rgb(70, 69, 69);
|
||||||
|
}
|
||||||
|
.table-aa > tbody > tr > td {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.table-aa > tbody > tr:last-child {
|
.table-aa > tbody > tr:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* highlight active menu items
|
/* highlight active menu items
|
||||||
|
@ -70,8 +70,8 @@ def _current_notifications() -> dict:
|
|||||||
_fetch_notification_issues_from_gitlab,
|
_fetch_notification_issues_from_gitlab,
|
||||||
NOTIFICATION_CACHE_TIME
|
NOTIFICATION_CACHE_TIME
|
||||||
)
|
)
|
||||||
except requests.RequestException:
|
except requests.HTTPError:
|
||||||
logger.exception('Error while getting gitlab notifications')
|
logger.warning('Error while getting gitlab notifications', exc_info=True)
|
||||||
top_notifications = []
|
top_notifications = []
|
||||||
else:
|
else:
|
||||||
if notifications:
|
if notifications:
|
||||||
@ -95,8 +95,8 @@ def _current_version_summary() -> dict:
|
|||||||
tags = cache.get_or_set(
|
tags = cache.get_or_set(
|
||||||
'git_release_tags', _fetch_tags_from_gitlab, TAG_CACHE_TIME
|
'git_release_tags', _fetch_tags_from_gitlab, TAG_CACHE_TIME
|
||||||
)
|
)
|
||||||
except requests.RequestException:
|
except requests.HTTPError:
|
||||||
logger.exception('Error while getting gitlab release tags')
|
logger.warning('Error while getting gitlab release tags', exc_info=True)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
if not tags:
|
if not tags:
|
||||||
|
@ -26,7 +26,7 @@ DISCORD_SYNC_NAMES = False
|
|||||||
|
|
||||||
CELERYBEAT_SCHEDULE['discord.update_all_usernames'] = {
|
CELERYBEAT_SCHEDULE['discord.update_all_usernames'] = {
|
||||||
'task': 'discord.update_all_usernames',
|
'task': 'discord.update_all_usernames',
|
||||||
'schedule': crontab(hour='*/12'),
|
'schedule': crontab(minute=0, hour='*/12'),
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user