mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-12-06 04:41:41 +01:00
remove trailing whitespaces
This commit is contained in:
parent
10bd77d761
commit
8c3df89d52
@ -1,4 +1,5 @@
|
|||||||
stages:
|
stages:
|
||||||
|
- pre-commit
|
||||||
- gitlab
|
- gitlab
|
||||||
- test
|
- test
|
||||||
- deploy
|
- deploy
|
||||||
@ -13,6 +14,18 @@ before_script:
|
|||||||
- python -V
|
- python -V
|
||||||
- pip install wheel tox
|
- pip install wheel tox
|
||||||
|
|
||||||
|
pre-commit-check:
|
||||||
|
stage: pre-commit
|
||||||
|
image: python:3.6-buster
|
||||||
|
variables:
|
||||||
|
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- ${PRE_COMMIT_HOME}
|
||||||
|
script:
|
||||||
|
- pip install pre-commit
|
||||||
|
- pre-commit run --all-files
|
||||||
|
|
||||||
sast:
|
sast:
|
||||||
stage: gitlab
|
stage: gitlab
|
||||||
before_script: []
|
before_script: []
|
||||||
@ -27,7 +40,7 @@ dependency_scanning:
|
|||||||
|
|
||||||
test-3.7-core:
|
test-3.7-core:
|
||||||
image: python:3.7-buster
|
image: python:3.7-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py37-core
|
- tox -e py37-core
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@ -36,7 +49,7 @@ test-3.7-core:
|
|||||||
|
|
||||||
test-3.8-core:
|
test-3.8-core:
|
||||||
image: python:3.8-buster
|
image: python:3.8-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py38-core
|
- tox -e py38-core
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@ -45,7 +58,7 @@ test-3.8-core:
|
|||||||
|
|
||||||
test-3.9-core:
|
test-3.9-core:
|
||||||
image: python:3.9-buster
|
image: python:3.9-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py39-core
|
- tox -e py39-core
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@ -54,7 +67,7 @@ test-3.9-core:
|
|||||||
|
|
||||||
test-3.7-all:
|
test-3.7-all:
|
||||||
image: python:3.7-buster
|
image: python:3.7-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py37-all
|
- tox -e py37-all
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@ -63,7 +76,7 @@ test-3.7-all:
|
|||||||
|
|
||||||
test-3.8-all:
|
test-3.8-all:
|
||||||
image: python:3.8-buster
|
image: python:3.8-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py38-all
|
- tox -e py38-all
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@ -72,7 +85,7 @@ test-3.8-all:
|
|||||||
|
|
||||||
test-3.9-all:
|
test-3.9-all:
|
||||||
image: python:3.9-buster
|
image: python:3.9-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py39-all
|
- tox -e py39-all
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@ -91,4 +104,4 @@ deploy_production:
|
|||||||
- twine upload dist/*
|
- twine upload dist/*
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_COMMIT_TAG
|
- if: $CI_COMMIT_TAG
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
# Bug
|
# Bug
|
||||||
|
|
||||||
- I have searched [issues](https://gitlab.com/allianceauth/allianceauth/issues?scope=all&utf8=%E2%9C%93&state=all) (Y/N):
|
- I have searched [issues](https://gitlab.com/allianceauth/allianceauth/issues?scope=all&utf8=%E2%9C%93&state=all) (Y/N):
|
||||||
- What Version of Alliance Auth:
|
- What Version of Alliance Auth:
|
||||||
- What Operating System:
|
- What Operating System:
|
||||||
- Version of other components relevant to issue eg. Service, Database:
|
- Version of other components relevant to issue eg. Service, Database:
|
||||||
|
|
||||||
Please include a brief description of your issue here.
|
Please include a brief description of your issue here.
|
||||||
|
|||||||
16
.pre-commit-config.yaml
Normal file
16
.pre-commit-config.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Apply to all files without committing:
|
||||||
|
# pre-commit run --all-files
|
||||||
|
# Update this file:
|
||||||
|
# pre-commit autoupdate
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v3.4.0
|
||||||
|
hooks:
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: check-json
|
||||||
|
- id: check-xml
|
||||||
|
- id: check-yaml
|
||||||
|
- id: fix-byte-order-marker
|
||||||
|
- id: trailing-whitespace
|
||||||
|
exclude: \.(min\.css|min\.js|po|mo)$
|
||||||
@ -84,7 +84,7 @@ class UserProfileInline(admin.StackedInline):
|
|||||||
if request.user.is_superuser:
|
if request.user.is_superuser:
|
||||||
query |= Q(userprofile__isnull=True)
|
query |= Q(userprofile__isnull=True)
|
||||||
else:
|
else:
|
||||||
query |= Q(character_ownership__user=obj)
|
query |= Q(character_ownership__user=obj)
|
||||||
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):
|
||||||
@ -123,26 +123,26 @@ def user_username(obj):
|
|||||||
|
|
||||||
works for both User objects and objects with `user` as FK to User
|
works for both User objects and objects with `user` as FK to User
|
||||||
To be used for all user based admin lists
|
To be used for all user based admin lists
|
||||||
"""
|
"""
|
||||||
link = reverse(
|
link = reverse(
|
||||||
'admin:{}_{}_change'.format(
|
'admin:{}_{}_change'.format(
|
||||||
obj._meta.app_label,
|
obj._meta.app_label,
|
||||||
type(obj).__name__.lower()
|
type(obj).__name__.lower()
|
||||||
),
|
),
|
||||||
args=(obj.pk,)
|
args=(obj.pk,)
|
||||||
)
|
)
|
||||||
user_obj = obj.user if hasattr(obj, 'user') else obj
|
user_obj = obj.user if hasattr(obj, 'user') else obj
|
||||||
if user_obj.profile.main_character:
|
if user_obj.profile.main_character:
|
||||||
return format_html(
|
return format_html(
|
||||||
'<strong><a href="{}">{}</a></strong><br>{}',
|
'<strong><a href="{}">{}</a></strong><br>{}',
|
||||||
link,
|
link,
|
||||||
user_obj.username,
|
user_obj.username,
|
||||||
user_obj.profile.main_character.character_name
|
user_obj.profile.main_character.character_name
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return format_html(
|
return format_html(
|
||||||
'<strong><a href="{}">{}</a></strong>',
|
'<strong><a href="{}">{}</a></strong>',
|
||||||
link,
|
link,
|
||||||
user_obj.username,
|
user_obj.username,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -160,16 +160,16 @@ def user_main_organization(obj):
|
|||||||
user_obj = obj.user if hasattr(obj, 'user') else obj
|
user_obj = obj.user if hasattr(obj, 'user') else obj
|
||||||
if not user_obj.profile.main_character:
|
if not user_obj.profile.main_character:
|
||||||
result = None
|
result = None
|
||||||
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(
|
result = format_html(
|
||||||
'{}<br>{}',
|
'{}<br>{}',
|
||||||
corporation,
|
corporation,
|
||||||
user_obj.profile.main_character.alliance_name
|
user_obj.profile.main_character.alliance_name
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
result = corporation
|
result = corporation
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ class MainCorporationsFilter(admin.SimpleListFilter):
|
|||||||
def queryset(self, request, qs):
|
def queryset(self, request, qs):
|
||||||
if self.value() is None:
|
if self.value() is None:
|
||||||
return qs.all()
|
return qs.all()
|
||||||
else:
|
else:
|
||||||
if qs.model == User:
|
if qs.model == User:
|
||||||
return qs.filter(
|
return qs.filter(
|
||||||
profile__main_character__corporation_id=self.value()
|
profile__main_character__corporation_id=self.value()
|
||||||
@ -209,7 +209,7 @@ class MainCorporationsFilter(admin.SimpleListFilter):
|
|||||||
return qs.filter(
|
return qs.filter(
|
||||||
user__profile__main_character__corporation_id=self.value()
|
user__profile__main_character__corporation_id=self.value()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MainAllianceFilter(admin.SimpleListFilter):
|
class MainAllianceFilter(admin.SimpleListFilter):
|
||||||
"""Custom filter to filter on alliances from mains only
|
"""Custom filter to filter on alliances from mains only
|
||||||
@ -234,16 +234,16 @@ class MainAllianceFilter(admin.SimpleListFilter):
|
|||||||
def queryset(self, request, qs):
|
def queryset(self, request, qs):
|
||||||
if self.value() is None:
|
if self.value() is None:
|
||||||
return qs.all()
|
return qs.all()
|
||||||
else:
|
else:
|
||||||
if qs.model == User:
|
if qs.model == User:
|
||||||
return qs.filter(profile__main_character__alliance_id=self.value())
|
return qs.filter(profile__main_character__alliance_id=self.value())
|
||||||
else:
|
else:
|
||||||
return qs.filter(
|
return qs.filter(
|
||||||
user__profile__main_character__alliance_id=self.value()
|
user__profile__main_character__alliance_id=self.value()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_main_character_model(modeladmin, request, queryset):
|
|
||||||
|
def update_main_character_model(modeladmin, request, queryset):
|
||||||
tasks_count = 0
|
tasks_count = 0
|
||||||
for obj in queryset:
|
for obj in queryset:
|
||||||
if obj.profile.main_character:
|
if obj.profile.main_character:
|
||||||
@ -251,7 +251,7 @@ def update_main_character_model(modeladmin, request, queryset):
|
|||||||
tasks_count += 1
|
tasks_count += 1
|
||||||
|
|
||||||
modeladmin.message_user(
|
modeladmin.message_user(
|
||||||
request,
|
request,
|
||||||
'Update from ESI started for {} characters'.format(tasks_count)
|
'Update from ESI started for {} characters'.format(tasks_count)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ update_main_character_model.short_description = \
|
|||||||
|
|
||||||
class UserAdmin(BaseUserAdmin):
|
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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
css = {
|
css = {
|
||||||
"all": ("authentication/css/admin.css",)
|
"all": ("authentication/css/admin.css",)
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super().get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
return qs.prefetch_related("character_ownerships__character", "groups")
|
return qs.prefetch_related("character_ownerships__character", "groups")
|
||||||
@ -279,8 +279,8 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
actions = super(BaseUserAdmin, self).get_actions(request)
|
actions = super(BaseUserAdmin, self).get_actions(request)
|
||||||
|
|
||||||
actions[update_main_character_model.__name__] = (
|
actions[update_main_character_model.__name__] = (
|
||||||
update_main_character_model,
|
update_main_character_model,
|
||||||
update_main_character_model.__name__,
|
update_main_character_model.__name__,
|
||||||
update_main_character_model.short_description
|
update_main_character_model.short_description
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -290,21 +290,21 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
if svc.update_groups.__module__ != ServicesHook.update_groups.__module__:
|
if svc.update_groups.__module__ != ServicesHook.update_groups.__module__:
|
||||||
action = make_service_hooks_update_groups_action(svc)
|
action = make_service_hooks_update_groups_action(svc)
|
||||||
actions[action.__name__] = (
|
actions[action.__name__] = (
|
||||||
action,
|
action,
|
||||||
action.__name__,
|
action.__name__,
|
||||||
action.short_description
|
action.short_description
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create sync nickname action if service implements it
|
# Create sync nickname action if service implements it
|
||||||
if svc.sync_nickname.__module__ != ServicesHook.sync_nickname.__module__:
|
if svc.sync_nickname.__module__ != ServicesHook.sync_nickname.__module__:
|
||||||
action = make_service_hooks_sync_nickname_action(svc)
|
action = make_service_hooks_sync_nickname_action(svc)
|
||||||
actions[action.__name__] = (
|
actions[action.__name__] = (
|
||||||
action, action.__name__,
|
action, action.__name__,
|
||||||
action.short_description
|
action.short_description
|
||||||
)
|
)
|
||||||
return actions
|
return actions
|
||||||
|
|
||||||
def _list_2_html_w_tooltips(self, my_items: list, max_items: int) -> str:
|
def _list_2_html_w_tooltips(self, my_items: list, max_items: int) -> str:
|
||||||
"""converts list of strings into HTML with cutoff and tooltip"""
|
"""converts list of strings into HTML with cutoff and tooltip"""
|
||||||
items_truncated_str = ', '.join(my_items[:max_items])
|
items_truncated_str = ', '.join(my_items[:max_items])
|
||||||
if not my_items:
|
if not my_items:
|
||||||
@ -320,27 +320,27 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
items_truncated_str
|
items_truncated_str
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
inlines = BaseUserAdmin.inlines + [UserProfileInline]
|
inlines = BaseUserAdmin.inlines + [UserProfileInline]
|
||||||
ordering = ('username', )
|
ordering = ('username', )
|
||||||
list_select_related = ('profile__state', 'profile__main_character')
|
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,
|
||||||
'_state',
|
'_state',
|
||||||
'_groups',
|
'_groups',
|
||||||
user_main_organization,
|
user_main_organization,
|
||||||
'_characters',
|
'_characters',
|
||||||
'is_active',
|
'is_active',
|
||||||
'date_joined',
|
'date_joined',
|
||||||
'_role'
|
'_role'
|
||||||
)
|
)
|
||||||
list_display_links = None
|
list_display_links = None
|
||||||
list_filter = (
|
list_filter = (
|
||||||
'profile__state',
|
'profile__state',
|
||||||
'groups',
|
'groups',
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
'is_active',
|
'is_active',
|
||||||
'date_joined',
|
'date_joined',
|
||||||
@ -348,32 +348,32 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
'is_superuser'
|
'is_superuser'
|
||||||
)
|
)
|
||||||
search_fields = (
|
search_fields = (
|
||||||
'username',
|
'username',
|
||||||
'character_ownerships__character__character_name'
|
'character_ownerships__character__character_name'
|
||||||
)
|
)
|
||||||
|
|
||||||
def _characters(self, obj):
|
def _characters(self, obj):
|
||||||
character_ownerships = list(obj.character_ownerships.all())
|
character_ownerships = list(obj.character_ownerships.all())
|
||||||
characters = [obj.character.character_name for obj in character_ownerships]
|
characters = [obj.character.character_name for obj in character_ownerships]
|
||||||
return self._list_2_html_w_tooltips(
|
return self._list_2_html_w_tooltips(
|
||||||
sorted(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
|
||||||
|
|
||||||
_state.short_description = 'state'
|
_state.short_description = 'state'
|
||||||
_state.admin_order_field = 'profile__state'
|
_state.admin_order_field = 'profile__state'
|
||||||
|
|
||||||
def _groups(self, obj):
|
def _groups(self, obj):
|
||||||
my_groups = sorted([group.name for group in list(obj.groups.all())])
|
my_groups = sorted([group.name for group in list(obj.groups.all())])
|
||||||
return self._list_2_html_w_tooltips(
|
return self._list_2_html_w_tooltips(
|
||||||
my_groups, AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
my_groups, AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
||||||
)
|
)
|
||||||
|
|
||||||
_groups.short_description = 'groups'
|
_groups.short_description = 'groups'
|
||||||
|
|
||||||
def _role(self, obj):
|
def _role(self, obj):
|
||||||
@ -382,11 +382,11 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
elif obj.is_staff:
|
elif obj.is_staff:
|
||||||
role = 'Staff'
|
role = 'Staff'
|
||||||
else:
|
else:
|
||||||
role = 'User'
|
role = 'User'
|
||||||
return role
|
return role
|
||||||
|
|
||||||
_role.short_description = 'role'
|
_role.short_description = 'role'
|
||||||
|
|
||||||
def has_change_permission(self, request, obj=None):
|
def has_change_permission(self, request, obj=None):
|
||||||
return request.user.has_perm('auth.change_user')
|
return request.user.has_perm('auth.change_user')
|
||||||
|
|
||||||
@ -404,10 +404,10 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
|
|
||||||
|
|
||||||
@admin.register(State)
|
@admin.register(State)
|
||||||
class StateAdmin(admin.ModelAdmin):
|
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):
|
def get_queryset(self, request):
|
||||||
qs = super().get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
return qs.annotate(user_count=Count("userprofile__id"))
|
return qs.annotate(user_count=Count("userprofile__id"))
|
||||||
@ -423,17 +423,17 @@ class StateAdmin(admin.ModelAdmin):
|
|||||||
}),
|
}),
|
||||||
('Membership', {
|
('Membership', {
|
||||||
'fields': (
|
'fields': (
|
||||||
'public',
|
'public',
|
||||||
'member_characters',
|
'member_characters',
|
||||||
'member_corporations',
|
'member_corporations',
|
||||||
'member_alliances'
|
'member_alliances'
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
filter_horizontal = [
|
filter_horizontal = [
|
||||||
'member_characters',
|
'member_characters',
|
||||||
'member_corporations',
|
'member_corporations',
|
||||||
'member_alliances',
|
'member_alliances',
|
||||||
'permissions'
|
'permissions'
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -463,16 +463,16 @@ class StateAdmin(admin.ModelAdmin):
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return super(StateAdmin, self).get_fieldsets(request, obj=obj)
|
return super(StateAdmin, self).get_fieldsets(request, obj=obj)
|
||||||
|
|
||||||
|
|
||||||
class BaseOwnershipAdmin(admin.ModelAdmin):
|
class BaseOwnershipAdmin(admin.ModelAdmin):
|
||||||
class Media:
|
class Media:
|
||||||
css = {
|
css = {
|
||||||
"all": ("authentication/css/admin.css",)
|
"all": ("authentication/css/admin.css",)
|
||||||
}
|
}
|
||||||
|
|
||||||
list_select_related = (
|
list_select_related = (
|
||||||
'user__profile__state', 'user__profile__main_character', 'character')
|
'user__profile__state', 'user__profile__main_character', 'character')
|
||||||
list_display = (
|
list_display = (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
@ -480,13 +480,13 @@ class BaseOwnershipAdmin(admin.ModelAdmin):
|
|||||||
'character',
|
'character',
|
||||||
)
|
)
|
||||||
search_fields = (
|
search_fields = (
|
||||||
'user__username',
|
'user__username',
|
||||||
'character__character_name',
|
'character__character_name',
|
||||||
'character__corporation_name',
|
'character__corporation_name',
|
||||||
'character__alliance_name'
|
'character__alliance_name'
|
||||||
)
|
)
|
||||||
list_filter = (
|
list_filter = (
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,14 @@ from django.conf import settings
|
|||||||
|
|
||||||
|
|
||||||
def _clean_setting(
|
def _clean_setting(
|
||||||
name: str,
|
name: str,
|
||||||
default_value: object,
|
default_value: object,
|
||||||
min_value: int = None,
|
min_value: int = None,
|
||||||
max_value: int = None,
|
max_value: int = None,
|
||||||
required_type: type = None
|
required_type: type = None
|
||||||
):
|
):
|
||||||
"""cleans the input for a custom setting
|
"""cleans the input for a custom setting
|
||||||
|
|
||||||
Will use `default_value` if settings does not exit or has the wrong type
|
Will use `default_value` if settings does not exit or has the wrong type
|
||||||
or is outside define boundaries (for int only)
|
or is outside define boundaries (for int only)
|
||||||
|
|
||||||
@ -18,22 +18,22 @@ def _clean_setting(
|
|||||||
Will assume `min_value` of 0 for int (can be overriden)
|
Will assume `min_value` of 0 for int (can be overriden)
|
||||||
|
|
||||||
Returns cleaned value for setting
|
Returns cleaned value for setting
|
||||||
"""
|
"""
|
||||||
if default_value is None and not required_type:
|
if default_value is None and not required_type:
|
||||||
raise ValueError('You must specify a required_type for None defaults')
|
raise ValueError('You must specify a required_type for None defaults')
|
||||||
|
|
||||||
if not required_type:
|
if not required_type:
|
||||||
required_type = type(default_value)
|
required_type = type(default_value)
|
||||||
|
|
||||||
if min_value is None and required_type == int:
|
if min_value is None and required_type == int:
|
||||||
min_value = 0
|
min_value = 0
|
||||||
|
|
||||||
if (hasattr(settings, name)
|
if (hasattr(settings, name)
|
||||||
and isinstance(getattr(settings, name), required_type)
|
and isinstance(getattr(settings, name), required_type)
|
||||||
and (min_value is None or getattr(settings, name) >= min_value)
|
and (min_value is None or getattr(settings, name) >= min_value)
|
||||||
and (max_value is None or getattr(settings, name) <= max_value)
|
and (max_value is None or getattr(settings, name) <= max_value)
|
||||||
):
|
):
|
||||||
return getattr(settings, name)
|
return getattr(settings, name)
|
||||||
else:
|
else:
|
||||||
return default_value
|
return default_value
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,9 @@ logger = logging.getLogger(__name__)
|
|||||||
class StateBackend(ModelBackend):
|
class StateBackend(ModelBackend):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_state_permissions(user_obj):
|
def _get_state_permissions(user_obj):
|
||||||
"""returns permissions for state of given user object"""
|
"""returns permissions for state of given user object"""
|
||||||
if hasattr(user_obj, "profile") and user_obj.profile:
|
if hasattr(user_obj, "profile") and user_obj.profile:
|
||||||
return Permission.objects.filter(state=user_obj.profile.state)
|
return Permission.objects.filter(state=user_obj.profile.state)
|
||||||
else:
|
else:
|
||||||
return Permission.objects.none()
|
return Permission.objects.none()
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ def create_permissions(apps, schema_editor):
|
|||||||
Permission = apps.get_model('auth', 'Permission')
|
Permission = apps.get_model('auth', 'Permission')
|
||||||
ct = ContentType.objects.get_for_model(User)
|
ct = ContentType.objects.get_for_model(User)
|
||||||
Permission.objects.get_or_create(codename="member", content_type=ct, name="member")
|
Permission.objects.get_or_create(codename="member", content_type=ct, name="member")
|
||||||
Permission.objects.get_or_create(codename="blue_member", content_type=ct, name="blue_member")
|
Permission.objects.get_or_create(codename="blue_member", content_type=ct, name="blue_member")
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|||||||
@ -74,7 +74,7 @@ class UserProfile(models.Model):
|
|||||||
logger.info('Updating {} state to {}'.format(self.user, self.state))
|
logger.info('Updating {} state to {}'.format(self.user, self.state))
|
||||||
self.save(update_fields=['state'])
|
self.save(update_fields=['state'])
|
||||||
notify(
|
notify(
|
||||||
self.user,
|
self.user,
|
||||||
_('State changed to: %s' % state),
|
_('State changed to: %s' % state),
|
||||||
_('Your user\'s state is now: %(state)s')
|
_('Your user\'s state is now: %(state)s')
|
||||||
% ({'state': state}),
|
% ({'state': state}),
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
CSS for allianceauth admin site
|
CSS for allianceauth admin site
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* styling for profile pic */
|
/* styling for profile pic */
|
||||||
.img-circle {
|
.img-circle {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
.column-user_profile_pic {
|
.column-user_profile_pic {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@ -26,4 +26,4 @@ CSS for allianceauth admin site
|
|||||||
color: black ;
|
color: black ;
|
||||||
background-color: rgb(255, 255, 204) ;
|
background-color: rgb(255, 255, 204) ;
|
||||||
z-index: 1 ;
|
z-index: 1 ;
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="table visible-xs-block">
|
<div class="table visible-xs-block">
|
||||||
<p>
|
<p>
|
||||||
<img class="ra-avatar" src="{{ main.portrait_url_64 }}">
|
<img class="ra-avatar" src="{{ main.portrait_url_64 }}">
|
||||||
<img class="ra-avatar" src="{{ main.corporation_logo_url_64 }}">
|
<img class="ra-avatar" src="{{ main.corporation_logo_url_64 }}">
|
||||||
@ -74,7 +74,7 @@
|
|||||||
{{ main.corporation_name }}<br>
|
{{ main.corporation_name }}<br>
|
||||||
{{ main.alliance_name }}
|
{{ main.alliance_name }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
@ -121,7 +121,7 @@
|
|||||||
{% trans 'Characters' %}
|
{% trans 'Characters' %}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<table class="table table-aa hidden-xs">
|
<table class="table table-aa hidden-xs">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -132,20 +132,20 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for char in characters %}
|
{% for char in characters %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center"><img class="ra-avatar img-circle" src="{{ char.portrait_url_32 }}">
|
<td class="text-center"><img class="ra-avatar img-circle" src="{{ char.portrait_url_32 }}">
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">{{ char.character_name }}</td>
|
<td class="text-center">{{ char.character_name }}</td>
|
||||||
<td class="text-center">{{ char.corporation_name }}</td>
|
<td class="text-center">{{ char.corporation_name }}</td>
|
||||||
<td class="text-center">{{ char.alliance_name }}</td>
|
<td class="text-center">{{ char.alliance_name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<table class="table table-aa visible-xs-block" style="width: 100%">
|
<table class="table table-aa visible-xs-block" style="width: 100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for char in characters %}
|
{% for char in characters %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center" style="vertical-align: middle">
|
<td class="text-center" style="vertical-align: middle">
|
||||||
<img class="ra-avatar img-circle" src="{{ char.portrait_url_32 }}">
|
<img class="ra-avatar img-circle" src="{{ char.portrait_url_32 }}">
|
||||||
@ -154,7 +154,7 @@
|
|||||||
<strong>{{ char.character_name }}</strong><br>
|
<strong>{{ char.character_name }}</strong><br>
|
||||||
{{ char.corporation_name }}<br>
|
{{ char.corporation_name }}<br>
|
||||||
{{ char.alliance_name|default:"" }}
|
{{ char.alliance_name|default:"" }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{% extends 'public/middle_box.html' %}
|
{% extends 'public/middle_box.html' %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% block page_title %}Login{% endblock %}
|
{% block page_title %}Login{% endblock %}
|
||||||
{% block middle_box_content %}
|
{% block middle_box_content %}
|
||||||
<a href="{% url 'auth_sso_login' %}{% if request.GET.next %}?next={{request.GET.next}}{%endif%}">
|
<a href="{% url 'auth_sso_login' %}{% if request.GET.next %}?next={{request.GET.next}}{%endif%}">
|
||||||
<img class="img-responsive center-block" src="{% static 'img/sso/EVE_SSO_Login_Buttons_Large_Black.png' %}" border=0>
|
<img class="img-responsive center-block" src="{% static 'img/sso/EVE_SSO_Login_Buttons_Large_Black.png' %}" border=0>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -16,15 +16,15 @@ from allianceauth.tests.auth_utils import AuthUtils
|
|||||||
|
|
||||||
from ..admin import (
|
from ..admin import (
|
||||||
BaseUserAdmin,
|
BaseUserAdmin,
|
||||||
CharacterOwnershipAdmin,
|
CharacterOwnershipAdmin,
|
||||||
StateAdmin,
|
StateAdmin,
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
OwnershipRecordAdmin,
|
OwnershipRecordAdmin,
|
||||||
User,
|
User,
|
||||||
UserAdmin,
|
UserAdmin,
|
||||||
user_main_organization,
|
user_main_organization,
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
update_main_character_model,
|
update_main_character_model,
|
||||||
make_service_hooks_update_groups_action,
|
make_service_hooks_update_groups_action,
|
||||||
@ -36,7 +36,7 @@ from . import get_admin_change_view_url, get_admin_search_url
|
|||||||
MODULE_PATH = 'allianceauth.authentication.admin'
|
MODULE_PATH = 'allianceauth.authentication.admin'
|
||||||
|
|
||||||
|
|
||||||
class MockRequest(object):
|
class MockRequest(object):
|
||||||
def __init__(self, user=None):
|
def __init__(self, user=None):
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class TestCaseWithTestData(TestCase):
|
|||||||
EveAllianceInfo, EveCorporationInfo, EveCharacter, Group, User
|
EveAllianceInfo, EveCorporationInfo, EveCharacter, Group, User
|
||||||
]:
|
]:
|
||||||
MyModel.objects.all().delete()
|
MyModel.objects.all().delete()
|
||||||
|
|
||||||
# groups
|
# groups
|
||||||
cls.group_1 = Group.objects.create(
|
cls.group_1 = Group.objects.create(
|
||||||
name='Group 1'
|
name='Group 1'
|
||||||
@ -84,16 +84,16 @@ class TestCaseWithTestData(TestCase):
|
|||||||
alliance = EveAllianceInfo.objects.create(
|
alliance = EveAllianceInfo.objects.create(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
alliance_name='Wayne Enterprises',
|
alliance_name='Wayne Enterprises',
|
||||||
alliance_ticker='WE',
|
alliance_ticker='WE',
|
||||||
executor_corp_id=2001
|
executor_corp_id=2001
|
||||||
)
|
)
|
||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2001,
|
corporation_id=2001,
|
||||||
corporation_name='Wayne Technologies',
|
corporation_name='Wayne Technologies',
|
||||||
corporation_ticker='WT',
|
corporation_ticker='WT',
|
||||||
member_count=42,
|
member_count=42,
|
||||||
alliance=alliance
|
alliance=alliance
|
||||||
)
|
)
|
||||||
cls.user_1 = User.objects.create_user(
|
cls.user_1 = User.objects.create_user(
|
||||||
character_1.character_name.replace(' ', '_'),
|
character_1.character_name.replace(' ', '_'),
|
||||||
'abc@example.com',
|
'abc@example.com',
|
||||||
@ -111,7 +111,7 @@ class TestCaseWithTestData(TestCase):
|
|||||||
)
|
)
|
||||||
cls.user_1.profile.main_character = character_1
|
cls.user_1.profile.main_character = character_1
|
||||||
cls.user_1.profile.save()
|
cls.user_1.profile.save()
|
||||||
cls.user_1.groups.add(cls.group_1)
|
cls.user_1.groups.add(cls.group_1)
|
||||||
|
|
||||||
# user 2 - corp only, staff
|
# user 2 - corp only, staff
|
||||||
character_2 = EveCharacter.objects.create(
|
character_2 = EveCharacter.objects.create(
|
||||||
@ -125,7 +125,7 @@ class TestCaseWithTestData(TestCase):
|
|||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2002,
|
corporation_id=2002,
|
||||||
corporation_name='Daily Plane',
|
corporation_name='Daily Plane',
|
||||||
corporation_ticker='DP',
|
corporation_ticker='DP',
|
||||||
member_count=99,
|
member_count=99,
|
||||||
alliance=None
|
alliance=None
|
||||||
)
|
)
|
||||||
@ -144,7 +144,7 @@ class TestCaseWithTestData(TestCase):
|
|||||||
cls.user_2.groups.add(cls.group_2)
|
cls.user_2.groups.add(cls.group_2)
|
||||||
cls.user_2.is_staff = True
|
cls.user_2.is_staff = True
|
||||||
cls.user_2.save()
|
cls.user_2.save()
|
||||||
|
|
||||||
# user 3 - no main, no group, superuser
|
# user 3 - no main, no group, superuser
|
||||||
character_3 = EveCharacter.objects.create(
|
character_3 = EveCharacter.objects.create(
|
||||||
character_id=1101,
|
character_id=1101,
|
||||||
@ -157,7 +157,7 @@ class TestCaseWithTestData(TestCase):
|
|||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2101,
|
corporation_id=2101,
|
||||||
corporation_name='Lex Corp',
|
corporation_name='Lex Corp',
|
||||||
corporation_ticker='LC',
|
corporation_ticker='LC',
|
||||||
member_count=666,
|
member_count=666,
|
||||||
alliance=None
|
alliance=None
|
||||||
)
|
)
|
||||||
@ -186,25 +186,25 @@ def make_generic_search_request(ModelClass: type, search_term: str):
|
|||||||
username='superuser', password='secret', email='admin@example.com'
|
username='superuser', password='secret', email='admin@example.com'
|
||||||
)
|
)
|
||||||
c = Client()
|
c = Client()
|
||||||
c.login(username='superuser', password='secret')
|
c.login(username='superuser', password='secret')
|
||||||
return c.get(
|
return c.get(
|
||||||
'%s?q=%s' % (get_admin_search_url(ModelClass), quote(search_term))
|
'%s?q=%s' % (get_admin_search_url(ModelClass), quote(search_term))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCharacterOwnershipAdmin(TestCaseWithTestData):
|
class TestCharacterOwnershipAdmin(TestCaseWithTestData):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.modeladmin = CharacterOwnershipAdmin(
|
self.modeladmin = CharacterOwnershipAdmin(
|
||||||
model=User, admin_site=AdminSite()
|
model=User, admin_site=AdminSite()
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_change_view_loads_normally(self):
|
def test_change_view_loads_normally(self):
|
||||||
User.objects.create_superuser(
|
User.objects.create_superuser(
|
||||||
username='superuser', password='secret', email='admin@example.com'
|
username='superuser', password='secret', email='admin@example.com'
|
||||||
)
|
)
|
||||||
c = Client()
|
c = Client()
|
||||||
c.login(username='superuser', password='secret')
|
c.login(username='superuser', password='secret')
|
||||||
ownership = self.user_1.character_ownerships.first()
|
ownership = self.user_1.character_ownerships.first()
|
||||||
response = c.get(get_admin_change_view_url(ownership))
|
response = c.get(get_admin_change_view_url(ownership))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
@ -219,18 +219,18 @@ class TestCharacterOwnershipAdmin(TestCaseWithTestData):
|
|||||||
|
|
||||||
|
|
||||||
class TestOwnershipRecordAdmin(TestCaseWithTestData):
|
class TestOwnershipRecordAdmin(TestCaseWithTestData):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.modeladmin = OwnershipRecordAdmin(
|
self.modeladmin = OwnershipRecordAdmin(
|
||||||
model=User, admin_site=AdminSite()
|
model=User, admin_site=AdminSite()
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_change_view_loads_normally(self):
|
def test_change_view_loads_normally(self):
|
||||||
User.objects.create_superuser(
|
User.objects.create_superuser(
|
||||||
username='superuser', password='secret', email='admin@example.com'
|
username='superuser', password='secret', email='admin@example.com'
|
||||||
)
|
)
|
||||||
c = Client()
|
c = Client()
|
||||||
c.login(username='superuser', password='secret')
|
c.login(username='superuser', password='secret')
|
||||||
ownership_record = OwnershipRecord.objects\
|
ownership_record = OwnershipRecord.objects\
|
||||||
.filter(user=self.user_1)\
|
.filter(user=self.user_1)\
|
||||||
.first()
|
.first()
|
||||||
@ -245,23 +245,23 @@ class TestOwnershipRecordAdmin(TestCaseWithTestData):
|
|||||||
|
|
||||||
|
|
||||||
class TestStateAdmin(TestCaseWithTestData):
|
class TestStateAdmin(TestCaseWithTestData):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.modeladmin = StateAdmin(
|
self.modeladmin = StateAdmin(
|
||||||
model=User, admin_site=AdminSite()
|
model=User, admin_site=AdminSite()
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_change_view_loads_normally(self):
|
def test_change_view_loads_normally(self):
|
||||||
User.objects.create_superuser(
|
User.objects.create_superuser(
|
||||||
username='superuser', password='secret', email='admin@example.com'
|
username='superuser', password='secret', email='admin@example.com'
|
||||||
)
|
)
|
||||||
c = Client()
|
c = Client()
|
||||||
c.login(username='superuser', password='secret')
|
c.login(username='superuser', password='secret')
|
||||||
|
|
||||||
guest_state = AuthUtils.get_guest_state()
|
guest_state = AuthUtils.get_guest_state()
|
||||||
response = c.get(get_admin_change_view_url(guest_state))
|
response = c.get(get_admin_change_view_url(guest_state))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
member_state = AuthUtils.get_member_state()
|
member_state = AuthUtils.get_member_state()
|
||||||
response = c.get(get_admin_change_view_url(member_state))
|
response = c.get(get_admin_change_view_url(member_state))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
@ -281,12 +281,12 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
model=User, admin_site=AdminSite()
|
model=User, admin_site=AdminSite()
|
||||||
)
|
)
|
||||||
self.character_1 = self.user_1.character_ownerships.first().character
|
self.character_1 = self.user_1.character_ownerships.first().character
|
||||||
|
|
||||||
def test_user_profile_pic_u1(self):
|
def test_user_profile_pic_u1(self):
|
||||||
expected = (
|
expected = (
|
||||||
'<img src="https://images.evetech.net/characters/1001/'
|
'<img src="https://images.evetech.net/characters/1001/'
|
||||||
'portrait?size=32" class="img-circle">'
|
'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):
|
||||||
@ -332,18 +332,18 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
expected = 'Lex Luthor'
|
expected = 'Lex Luthor'
|
||||||
result = self.modeladmin._characters(self.user_3)
|
result = self.modeladmin._characters(self.user_3)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_groups_u1(self):
|
def test_groups_u1(self):
|
||||||
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):
|
||||||
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):
|
||||||
result = self.modeladmin._groups(self.user_3)
|
result = self.modeladmin._groups(self.user_3)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
@ -387,7 +387,7 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
expected = None
|
expected = None
|
||||||
result = self.modeladmin._list_2_html_w_tooltips(items, 5)
|
result = self.modeladmin._list_2_html_w_tooltips(items, 5)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
# actions
|
# actions
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.UserAdmin.message_user', auto_spec=True)
|
@patch(MODULE_PATH + '.UserAdmin.message_user', auto_spec=True)
|
||||||
@ -401,14 +401,14 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
)
|
)
|
||||||
self.assertEqual(mock_task.delay.call_count, 2)
|
self.assertEqual(mock_task.delay.call_count, 2)
|
||||||
self.assertTrue(mock_message_user.called)
|
self.assertTrue(mock_message_user.called)
|
||||||
|
|
||||||
# filters
|
# filters
|
||||||
|
|
||||||
def test_filter_main_corporations(self):
|
def test_filter_main_corporations(self):
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
class UserAdminTest(BaseUserAdmin):
|
||||||
list_filter = (MainCorporationsFilter,)
|
list_filter = (MainCorporationsFilter,)
|
||||||
|
|
||||||
my_modeladmin = UserAdminTest(User, AdminSite())
|
my_modeladmin = UserAdminTest(User, AdminSite())
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
# Make sure the lookups are correct
|
||||||
@ -417,7 +417,7 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
filters = changelist.get_filters(request)
|
filters = changelist.get_filters(request)
|
||||||
filterspec = filters[0][0]
|
filterspec = filters[0][0]
|
||||||
expected = [
|
expected = [
|
||||||
(2002, 'Daily Planet'),
|
(2002, 'Daily Planet'),
|
||||||
(2001, 'Wayne Technologies'),
|
(2001, 'Wayne Technologies'),
|
||||||
]
|
]
|
||||||
@ -425,20 +425,20 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
|
|
||||||
# Make sure the correct queryset is returned
|
# Make sure the correct queryset is returned
|
||||||
request = self.factory.get(
|
request = self.factory.get(
|
||||||
'/',
|
'/',
|
||||||
{'main_corporation_id__exact': self.character_1.corporation_id}
|
{'main_corporation_id__exact': self.character_1.corporation_id}
|
||||||
)
|
)
|
||||||
request.user = self.user_1
|
request.user = self.user_1
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
queryset = changelist.get_queryset(request)
|
queryset = changelist.get_queryset(request)
|
||||||
expected = [self.user_1]
|
expected = [self.user_1]
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
self.assertSetEqual(set(queryset), set(expected))
|
||||||
|
|
||||||
def test_filter_main_alliances(self):
|
def test_filter_main_alliances(self):
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
class UserAdminTest(BaseUserAdmin):
|
||||||
list_filter = (MainAllianceFilter,)
|
list_filter = (MainAllianceFilter,)
|
||||||
|
|
||||||
my_modeladmin = UserAdminTest(User, AdminSite())
|
my_modeladmin = UserAdminTest(User, AdminSite())
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
# Make sure the lookups are correct
|
||||||
@ -447,17 +447,17 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
filters = changelist.get_filters(request)
|
filters = changelist.get_filters(request)
|
||||||
filterspec = filters[0][0]
|
filterspec = filters[0][0]
|
||||||
expected = [
|
expected = [
|
||||||
(3001, 'Wayne Enterprises'),
|
(3001, 'Wayne Enterprises'),
|
||||||
]
|
]
|
||||||
self.assertEqual(filterspec.lookup_choices, expected)
|
self.assertEqual(filterspec.lookup_choices, expected)
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
# Make sure the correct queryset is returned
|
||||||
request = self.factory.get(
|
request = self.factory.get(
|
||||||
'/',
|
'/',
|
||||||
{'main_alliance_id__exact': self.character_1.alliance_id}
|
{'main_alliance_id__exact': self.character_1.alliance_id}
|
||||||
)
|
)
|
||||||
request.user = self.user_1
|
request.user = self.user_1
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
queryset = changelist.get_queryset(request)
|
queryset = changelist.get_queryset(request)
|
||||||
expected = [self.user_1]
|
expected = [self.user_1]
|
||||||
@ -468,7 +468,7 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
username='superuser', password='secret', email='admin@example.com'
|
username='superuser', password='secret', email='admin@example.com'
|
||||||
)
|
)
|
||||||
c = Client()
|
c = Client()
|
||||||
c.login(username='superuser', password='secret')
|
c.login(username='superuser', password='secret')
|
||||||
response = c.get(get_admin_change_view_url(self.user_1))
|
response = c.get(get_admin_change_view_url(self.user_1))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
@ -485,8 +485,8 @@ class TestMakeServicesHooksActions(TestCaseWithTestData):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = 'My Service A'
|
self.name = 'My Service A'
|
||||||
|
|
||||||
def update_groups(self, user):
|
def update_groups(self, user):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -498,7 +498,7 @@ class TestMakeServicesHooksActions(TestCaseWithTestData):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = 'My Service B'
|
self.name = 'My Service B'
|
||||||
|
|
||||||
def update_groups(self, user):
|
def update_groups(self, user):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -510,32 +510,32 @@ 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)
|
||||||
action = make_service_hooks_update_groups_action(mock_service)
|
action = make_service_hooks_update_groups_action(mock_service)
|
||||||
action(MagicMock(), MagicMock(), [self.user_1])
|
action(MagicMock(), MagicMock(), [self.user_1])
|
||||||
self.assertTrue(mock_service.update_groups.called)
|
self.assertTrue(mock_service.update_groups.called)
|
||||||
|
|
||||||
def test_service_has_update_groups_bulk(self):
|
def test_service_has_update_groups_bulk(self):
|
||||||
service = self.MyServicesHookTypeB()
|
service = self.MyServicesHookTypeB()
|
||||||
mock_service = MagicMock(spec=service)
|
mock_service = MagicMock(spec=service)
|
||||||
action = make_service_hooks_update_groups_action(mock_service)
|
action = make_service_hooks_update_groups_action(mock_service)
|
||||||
action(MagicMock(), MagicMock(), [self.user_1])
|
action(MagicMock(), MagicMock(), [self.user_1])
|
||||||
self.assertFalse(mock_service.update_groups.called)
|
self.assertFalse(mock_service.update_groups.called)
|
||||||
self.assertTrue(mock_service.update_groups_bulk.called)
|
self.assertTrue(mock_service.update_groups_bulk.called)
|
||||||
|
|
||||||
def test_service_has_sync_nickname_only(self):
|
def test_service_has_sync_nickname_only(self):
|
||||||
service = self.MyServicesHookTypeA()
|
service = self.MyServicesHookTypeA()
|
||||||
mock_service = MagicMock(spec=service)
|
mock_service = MagicMock(spec=service)
|
||||||
action = make_service_hooks_sync_nickname_action(mock_service)
|
action = make_service_hooks_sync_nickname_action(mock_service)
|
||||||
action(MagicMock(), MagicMock(), [self.user_1])
|
action(MagicMock(), MagicMock(), [self.user_1])
|
||||||
self.assertTrue(mock_service.sync_nickname.called)
|
self.assertTrue(mock_service.sync_nickname.called)
|
||||||
|
|
||||||
def test_service_has_sync_nicknames_bulk(self):
|
def test_service_has_sync_nicknames_bulk(self):
|
||||||
service = self.MyServicesHookTypeB()
|
service = self.MyServicesHookTypeB()
|
||||||
mock_service = MagicMock(spec=service)
|
mock_service = MagicMock(spec=service)
|
||||||
action = make_service_hooks_sync_nickname_action(mock_service)
|
action = make_service_hooks_sync_nickname_action(mock_service)
|
||||||
action(MagicMock(), MagicMock(), [self.user_1])
|
action(MagicMock(), MagicMock(), [self.user_1])
|
||||||
self.assertFalse(mock_service.sync_nickname.called)
|
self.assertFalse(mock_service.sync_nickname.called)
|
||||||
|
|||||||
@ -9,19 +9,19 @@ MODULE_PATH = 'allianceauth.authentication'
|
|||||||
class TestSetAppSetting(TestCase):
|
class TestSetAppSetting(TestCase):
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.app_settings.settings')
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
def test_default_if_not_set(self, mock_settings):
|
def test_default_if_not_set(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.app_settings.settings')
|
@patch(MODULE_PATH + '.app_settings.settings')
|
||||||
def test_default_if_not_set_for_none(self, mock_settings):
|
def test_default_if_not_set_for_none(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
None,
|
None,
|
||||||
required_type=int
|
required_type=int
|
||||||
)
|
)
|
||||||
@ -31,8 +31,8 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_true_stays_true(self, mock_settings):
|
def test_true_stays_true(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = True
|
mock_settings.TEST_SETTING_DUMMY = True
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
self.assertEqual(result, True)
|
self.assertEqual(result, True)
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_false_stays_false(self, mock_settings):
|
def test_false_stays_false(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = False
|
mock_settings.TEST_SETTING_DUMMY = False
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False
|
False
|
||||||
)
|
)
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
@ -49,7 +49,7 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_default_for_invalid_type_bool(self, mock_settings):
|
def test_default_for_invalid_type_bool(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False
|
False
|
||||||
)
|
)
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
@ -58,7 +58,7 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_default_for_invalid_type_int(self, mock_settings):
|
def test_default_for_invalid_type_int(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
50
|
50
|
||||||
)
|
)
|
||||||
self.assertEqual(result, 50)
|
self.assertEqual(result, 50)
|
||||||
@ -67,7 +67,7 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_default_if_below_minimum_1(self, mock_settings):
|
def test_default_if_below_minimum_1(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = -5
|
mock_settings.TEST_SETTING_DUMMY = -5
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=50
|
default_value=50
|
||||||
)
|
)
|
||||||
self.assertEqual(result, 50)
|
self.assertEqual(result, 50)
|
||||||
@ -76,7 +76,7 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_default_if_below_minimum_2(self, mock_settings):
|
def test_default_if_below_minimum_2(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = -50
|
mock_settings.TEST_SETTING_DUMMY = -50
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=50,
|
default_value=50,
|
||||||
min_value=-10
|
min_value=-10
|
||||||
)
|
)
|
||||||
@ -86,7 +86,7 @@ class TestSetAppSetting(TestCase):
|
|||||||
def test_default_for_invalid_type_int(self, mock_settings):
|
def test_default_for_invalid_type_int(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = 1000
|
mock_settings.TEST_SETTING_DUMMY = 1000
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=50,
|
default_value=50,
|
||||||
max_value=100
|
max_value=100
|
||||||
)
|
)
|
||||||
@ -97,6 +97,6 @@ class TestSetAppSetting(TestCase):
|
|||||||
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
result = app_settings._clean_setting(
|
result = app_settings._clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=None
|
default_value=None
|
||||||
)
|
)
|
||||||
|
|||||||
@ -23,27 +23,27 @@ class TestStatePermissions(TestCase):
|
|||||||
self.permission_2 = AuthUtils.get_permission_by_name(PERMISSION_2)
|
self.permission_2 = AuthUtils.get_permission_by_name(PERMISSION_2)
|
||||||
|
|
||||||
# group
|
# group
|
||||||
self.group_1 = Group.objects.create(name="Group 1")
|
self.group_1 = Group.objects.create(name="Group 1")
|
||||||
self.group_2 = Group.objects.create(name="Group 2")
|
self.group_2 = Group.objects.create(name="Group 2")
|
||||||
|
|
||||||
# state
|
# state
|
||||||
self.state_1 = AuthUtils.get_member_state()
|
self.state_1 = AuthUtils.get_member_state()
|
||||||
self.state_2 = AuthUtils.create_state("Other State", 75)
|
self.state_2 = AuthUtils.create_state("Other State", 75)
|
||||||
|
|
||||||
# user
|
# user
|
||||||
self.user = AuthUtils.create_user("Bruce Wayne")
|
self.user = AuthUtils.create_user("Bruce Wayne")
|
||||||
self.main = AuthUtils.add_main_character_2(self.user, self.user.username, 123)
|
self.main = AuthUtils.add_main_character_2(self.user, self.user.username, 123)
|
||||||
|
|
||||||
def test_user_has_user_permissions(self):
|
def test_user_has_user_permissions(self):
|
||||||
self.user.user_permissions.add(self.permission_1)
|
self.user.user_permissions.add(self.permission_1)
|
||||||
|
|
||||||
user = User.objects.get(pk=self.user.pk)
|
user = User.objects.get(pk=self.user.pk)
|
||||||
self.assertTrue(user.has_perm(PERMISSION_1))
|
self.assertTrue(user.has_perm(PERMISSION_1))
|
||||||
|
|
||||||
def test_user_has_group_permissions(self):
|
def test_user_has_group_permissions(self):
|
||||||
self.group_1.permissions.add(self.permission_1)
|
self.group_1.permissions.add(self.permission_1)
|
||||||
self.user.groups.add(self.group_1)
|
self.user.groups.add(self.group_1)
|
||||||
|
|
||||||
user = User.objects.get(pk=self.user.pk)
|
user = User.objects.get(pk=self.user.pk)
|
||||||
self.assertTrue(user.has_perm(PERMISSION_1))
|
self.assertTrue(user.has_perm(PERMISSION_1))
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class TestStatePermissions(TestCase):
|
|||||||
self.assertTrue(user.has_perm(PERMISSION_1))
|
self.assertTrue(user.has_perm(PERMISSION_1))
|
||||||
|
|
||||||
def test_when_user_changes_state_perms_change_accordingly(self):
|
def test_when_user_changes_state_perms_change_accordingly(self):
|
||||||
self.state_1.permissions.add(self.permission_1)
|
self.state_1.permissions.add(self.permission_1)
|
||||||
self.state_1.member_characters.add(self.main)
|
self.state_1.member_characters.add(self.main)
|
||||||
user = User.objects.get(pk=self.user.pk)
|
user = User.objects.get(pk=self.user.pk)
|
||||||
self.assertTrue(user.has_perm(PERMISSION_1))
|
self.assertTrue(user.has_perm(PERMISSION_1))
|
||||||
@ -68,16 +68,16 @@ class TestStatePermissions(TestCase):
|
|||||||
self.assertTrue(user.has_perm(PERMISSION_2))
|
self.assertTrue(user.has_perm(PERMISSION_2))
|
||||||
|
|
||||||
def test_state_permissions_are_returned_for_current_user_object(self):
|
def test_state_permissions_are_returned_for_current_user_object(self):
|
||||||
# verify state permissions are returns for the current user object
|
# verify state permissions are returns for the current user object
|
||||||
# and not for it's instance in the database, which might be outdated
|
# and not for it's instance in the database, which might be outdated
|
||||||
self.state_1.permissions.add(self.permission_1)
|
self.state_1.permissions.add(self.permission_1)
|
||||||
self.state_2.permissions.add(self.permission_2)
|
self.state_2.permissions.add(self.permission_2)
|
||||||
self.state_1.member_characters.add(self.main)
|
self.state_1.member_characters.add(self.main)
|
||||||
user = User.objects.get(pk=self.user.pk)
|
user = User.objects.get(pk=self.user.pk)
|
||||||
user.profile.state = self.state_2
|
user.profile.state = self.state_2
|
||||||
self.assertFalse(user.has_perm(PERMISSION_1))
|
self.assertFalse(user.has_perm(PERMISSION_1))
|
||||||
self.assertTrue(user.has_perm(PERMISSION_2))
|
self.assertTrue(user.has_perm(PERMISSION_2))
|
||||||
|
|
||||||
|
|
||||||
class TestAuthenticate(TestCase):
|
class TestAuthenticate(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@ -10,9 +10,9 @@ from django.test import TestCase
|
|||||||
from allianceauth.templatetags.admin_status import (
|
from allianceauth.templatetags.admin_status import (
|
||||||
status_overview,
|
status_overview,
|
||||||
_fetch_list_from_gitlab,
|
_fetch_list_from_gitlab,
|
||||||
_current_notifications,
|
_current_notifications,
|
||||||
_current_version_summary,
|
_current_version_summary,
|
||||||
_fetch_notification_issues_from_gitlab,
|
_fetch_notification_issues_from_gitlab,
|
||||||
_latests_versions
|
_latests_versions
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -58,10 +58,10 @@ class TestStatusOverviewTag(TestCase):
|
|||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status._fetch_celery_queue_length')
|
@patch(MODULE_PATH + '.admin_status._fetch_celery_queue_length')
|
||||||
@patch(MODULE_PATH + '.admin_status._current_version_summary')
|
@patch(MODULE_PATH + '.admin_status._current_version_summary')
|
||||||
@patch(MODULE_PATH + '.admin_status._current_notifications')
|
@patch(MODULE_PATH + '.admin_status._current_notifications')
|
||||||
def test_status_overview(
|
def test_status_overview(
|
||||||
self,
|
self,
|
||||||
mock_current_notifications,
|
mock_current_notifications,
|
||||||
mock_current_version_info,
|
mock_current_version_info,
|
||||||
mock_fetch_celery_queue_length
|
mock_fetch_celery_queue_length
|
||||||
):
|
):
|
||||||
@ -82,7 +82,7 @@ class TestStatusOverviewTag(TestCase):
|
|||||||
}
|
}
|
||||||
mock_current_version_info.return_value = version_info
|
mock_current_version_info.return_value = version_info
|
||||||
mock_fetch_celery_queue_length.return_value = 3
|
mock_fetch_celery_queue_length.return_value = 3
|
||||||
|
|
||||||
result = status_overview()
|
result = status_overview()
|
||||||
expected = {
|
expected = {
|
||||||
'notifications': GITHUB_NOTIFICATION_ISSUES[:5],
|
'notifications': GITHUB_NOTIFICATION_ISSUES[:5],
|
||||||
@ -111,7 +111,7 @@ class TestNotifications(TestCase):
|
|||||||
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
|
# when
|
||||||
result = _fetch_notification_issues_from_gitlab()
|
result = _fetch_notification_issues_from_gitlab()
|
||||||
@ -127,13 +127,13 @@ class TestNotifications(TestCase):
|
|||||||
# then
|
# then
|
||||||
self.assertEqual(result['notifications'], GITHUB_NOTIFICATION_ISSUES[:5])
|
self.assertEqual(result['notifications'], GITHUB_NOTIFICATION_ISSUES[:5])
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_current_notifications_failed(self, requests_mocker):
|
def test_current_notifications_failed(self, requests_mocker):
|
||||||
# given
|
# 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, status_code=404)
|
requests_mocker.get(url, status_code=404)
|
||||||
# when
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
@ -163,7 +163,7 @@ class TestVersionTags(TestCase):
|
|||||||
|
|
||||||
@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
|
# given
|
||||||
mock_cache.get_or_set.return_value = GITHUB_TAGS
|
mock_cache.get_or_set.return_value = GITHUB_TAGS
|
||||||
# when
|
# when
|
||||||
@ -184,7 +184,7 @@ class TestVersionTags(TestCase):
|
|||||||
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, status_code=500)
|
requests_mocker.get(url, status_code=500)
|
||||||
# when
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
@ -197,7 +197,7 @@ class TestVersionTags(TestCase):
|
|||||||
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)
|
||||||
# when
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
@ -208,7 +208,7 @@ class TestVersionTags(TestCase):
|
|||||||
@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
|
# given
|
||||||
mock_cache.get_or_set.return_value = None
|
mock_cache.get_or_set.return_value = None
|
||||||
# when
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
# then
|
# then
|
||||||
@ -218,7 +218,7 @@ class TestVersionTags(TestCase):
|
|||||||
class TestLatestsVersion(TestCase):
|
class TestLatestsVersion(TestCase):
|
||||||
|
|
||||||
def test_all_version_types_defined(self):
|
def test_all_version_types_defined(self):
|
||||||
|
|
||||||
tags = create_tags_list(
|
tags = create_tags_list(
|
||||||
['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0']
|
['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0']
|
||||||
)
|
)
|
||||||
@ -229,7 +229,7 @@ class TestLatestsVersion(TestCase):
|
|||||||
self.assertEqual(beta, Pep440Version('2.1.1a1'))
|
self.assertEqual(beta, Pep440Version('2.1.1a1'))
|
||||||
|
|
||||||
def test_major_and_minor_not_defined_with_zero(self):
|
def test_major_and_minor_not_defined_with_zero(self):
|
||||||
|
|
||||||
tags = create_tags_list(
|
tags = create_tags_list(
|
||||||
['2.1.2', '2.1.1', '2.0.1', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0']
|
['2.1.2', '2.1.1', '2.0.1', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0']
|
||||||
)
|
)
|
||||||
@ -238,9 +238,9 @@ class TestLatestsVersion(TestCase):
|
|||||||
self.assertEqual(minor, Pep440Version('2.1.1'))
|
self.assertEqual(minor, Pep440Version('2.1.1'))
|
||||||
self.assertEqual(patch, Pep440Version('2.1.2'))
|
self.assertEqual(patch, Pep440Version('2.1.2'))
|
||||||
self.assertEqual(beta, Pep440Version('2.1.1a1'))
|
self.assertEqual(beta, Pep440Version('2.1.1a1'))
|
||||||
|
|
||||||
def test_can_ignore_invalid_versions(self):
|
def test_can_ignore_invalid_versions(self):
|
||||||
|
|
||||||
tags = create_tags_list(
|
tags = create_tags_list(
|
||||||
['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', 'invalid']
|
['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', 'invalid']
|
||||||
)
|
)
|
||||||
@ -252,9 +252,9 @@ class TestLatestsVersion(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestFetchListFromGitlab(TestCase):
|
class TestFetchListFromGitlab(TestCase):
|
||||||
|
|
||||||
page_size = 2
|
page_size = 2
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.url = (
|
self.url = (
|
||||||
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
||||||
@ -266,8 +266,8 @@ class TestFetchListFromGitlab(TestCase):
|
|||||||
page = int(request.qs['page'][0])
|
page = int(request.qs['page'][0])
|
||||||
start = (page - 1) * cls.page_size
|
start = (page - 1) * cls.page_size
|
||||||
end = start + cls.page_size
|
end = start + cls.page_size
|
||||||
return GITHUB_TAGS[start:end]
|
return GITHUB_TAGS[start:end]
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_can_fetch_one_page_with_header(self, requests_mocker):
|
def test_can_fetch_one_page_with_header(self, requests_mocker):
|
||||||
headers = {
|
headers = {
|
||||||
@ -279,7 +279,7 @@ class TestFetchListFromGitlab(TestCase):
|
|||||||
self.assertEqual(requests_mocker.call_count, 1)
|
self.assertEqual(requests_mocker.call_count, 1)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_can_fetch_one_page_wo_header(self, requests_mocker):
|
def test_can_fetch_one_page_wo_header(self, requests_mocker):
|
||||||
requests_mocker.get(self.url, json=GITHUB_TAGS)
|
requests_mocker.get(self.url, json=GITHUB_TAGS)
|
||||||
result = _fetch_list_from_gitlab(self.url)
|
result = _fetch_list_from_gitlab(self.url)
|
||||||
self.assertEqual(result, GITHUB_TAGS)
|
self.assertEqual(result, GITHUB_TAGS)
|
||||||
@ -296,7 +296,7 @@ class TestFetchListFromGitlab(TestCase):
|
|||||||
self.assertEqual(requests_mocker.call_count, 1)
|
self.assertEqual(requests_mocker.call_count, 1)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_can_fetch_multiple_pages(self, requests_mocker):
|
def test_can_fetch_multiple_pages(self, requests_mocker):
|
||||||
total_pages = ceil(len(GITHUB_TAGS) / self.page_size)
|
total_pages = ceil(len(GITHUB_TAGS) / self.page_size)
|
||||||
headers = {
|
headers = {
|
||||||
'x-total-pages': str(total_pages)
|
'x-total-pages': str(total_pages)
|
||||||
@ -307,7 +307,7 @@ class TestFetchListFromGitlab(TestCase):
|
|||||||
self.assertEqual(requests_mocker.call_count, total_pages)
|
self.assertEqual(requests_mocker.call_count, total_pages)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_can_fetch_given_number_of_pages_only(self, requests_mocker):
|
def test_can_fetch_given_number_of_pages_only(self, requests_mocker):
|
||||||
total_pages = ceil(len(GITHUB_TAGS) / self.page_size)
|
total_pages = ceil(len(GITHUB_TAGS) / self.page_size)
|
||||||
headers = {
|
headers = {
|
||||||
'x-total-pages': str(total_pages)
|
'x-total-pages': str(total_pages)
|
||||||
|
|||||||
@ -9,8 +9,8 @@ app_name = 'authentication'
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', views.index, name='index'),
|
url(r'^$', views.index, name='index'),
|
||||||
url(
|
url(
|
||||||
r'^account/login/$',
|
r'^account/login/$',
|
||||||
TemplateView.as_view(template_name='public/login.html'),
|
TemplateView.as_view(template_name='public/login.html'),
|
||||||
name='login'
|
name='login'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
@ -19,9 +19,9 @@ urlpatterns = [
|
|||||||
name='change_main_character'
|
name='change_main_character'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^account/characters/add/$',
|
r'^account/characters/add/$',
|
||||||
views.add_character,
|
views.add_character,
|
||||||
name='add_character'
|
name='add_character'
|
||||||
),
|
),
|
||||||
url(r'^dashboard/$', views.dashboard, name='dashboard'),
|
url(r'^dashboard/$', views.dashboard, name='dashboard'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -16,8 +16,8 @@ from esi.decorators import token_required
|
|||||||
from esi.models import Token
|
from esi.models import Token
|
||||||
|
|
||||||
from django_registration.backends.activation.views import (
|
from django_registration.backends.activation.views import (
|
||||||
RegistrationView as BaseRegistrationView,
|
RegistrationView as BaseRegistrationView,
|
||||||
ActivationView as BaseActivationView,
|
ActivationView as BaseActivationView,
|
||||||
REGISTRATION_SALT
|
REGISTRATION_SALT
|
||||||
)
|
)
|
||||||
from django_registration.signals import user_registered
|
from django_registration.signals import user_registered
|
||||||
@ -52,7 +52,7 @@ def dashboard(request):
|
|||||||
.filter(character_ownership__user=request.user)\
|
.filter(character_ownership__user=request.user)\
|
||||||
.select_related()\
|
.select_related()\
|
||||||
.order_by('character_name')
|
.order_by('character_name')
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'groups': groups,
|
'groups': groups,
|
||||||
'characters': characters
|
'characters': characters
|
||||||
@ -71,7 +71,7 @@ def main_character_change(request, token):
|
|||||||
co = CharacterOwnership.objects.create_by_token(token)
|
co = CharacterOwnership.objects.create_by_token(token)
|
||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
_('Cannot change main character to %(char)s: character owned by a different account.') % ({'char': token.character_name})
|
_('Cannot change main character to %(char)s: character owned by a different account.') % ({'char': token.character_name})
|
||||||
)
|
)
|
||||||
co = None
|
co = None
|
||||||
@ -138,7 +138,7 @@ class RegistrationView(BaseRegistrationView):
|
|||||||
template_name = "public/register.html"
|
template_name = "public/register.html"
|
||||||
email_body_template = "registration/activation_email.txt"
|
email_body_template = "registration/activation_email.txt"
|
||||||
email_subject_template = "registration/activation_email_subject.txt"
|
email_subject_template = "registration/activation_email_subject.txt"
|
||||||
success_url = reverse_lazy('registration_complete')
|
success_url = reverse_lazy('registration_complete')
|
||||||
|
|
||||||
def get_success_url(self, user):
|
def get_success_url(self, user):
|
||||||
if not getattr(settings, 'REGISTRATION_VERIFY_EMAIL', True):
|
if not getattr(settings, 'REGISTRATION_VERIFY_EMAIL', True):
|
||||||
@ -181,8 +181,8 @@ class RegistrationView(BaseRegistrationView):
|
|||||||
# Step 3
|
# Step 3
|
||||||
class ActivationView(BaseActivationView):
|
class ActivationView(BaseActivationView):
|
||||||
template_name = "registration/activate.html"
|
template_name = "registration/activate.html"
|
||||||
success_url = reverse_lazy('registration_activation_complete')
|
success_url = reverse_lazy('registration_activation_complete')
|
||||||
|
|
||||||
def validate_key(self, activation_key):
|
def validate_key(self, activation_key):
|
||||||
try:
|
try:
|
||||||
dump = signing.loads(activation_key, salt=REGISTRATION_SALT,
|
dump = signing.loads(activation_key, salt=REGISTRATION_SALT,
|
||||||
|
|||||||
@ -37,7 +37,7 @@ class CorpStatsQuerySet(models.QuerySet):
|
|||||||
return self.filter(query)
|
return self.filter(query)
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
logger.debug('User %s has no main character. No corpstats visible.' % user)
|
logger.debug('User %s has no main character. No corpstats visible.' % user)
|
||||||
return self.none()
|
return self.none()
|
||||||
|
|
||||||
|
|
||||||
class CorpStatsManager(models.Manager):
|
class CorpStatsManager(models.Manager):
|
||||||
|
|||||||
@ -97,7 +97,7 @@ class EveAllianceForm(EveEntityForm):
|
|||||||
@admin.register(EveCorporationInfo)
|
@admin.register(EveCorporationInfo)
|
||||||
class EveCorporationInfoAdmin(admin.ModelAdmin):
|
class EveCorporationInfoAdmin(admin.ModelAdmin):
|
||||||
search_fields = ['corporation_name']
|
search_fields = ['corporation_name']
|
||||||
list_display = ('corporation_name', 'alliance')
|
list_display = ('corporation_name', 'alliance')
|
||||||
list_select_related = ('alliance',)
|
list_select_related = ('alliance',)
|
||||||
list_filter = (('alliance', admin.RelatedOnlyFieldListFilter),)
|
list_filter = (('alliance', admin.RelatedOnlyFieldListFilter),)
|
||||||
ordering = ('corporation_name',)
|
ordering = ('corporation_name',)
|
||||||
@ -114,9 +114,9 @@ class EveCorporationInfoAdmin(admin.ModelAdmin):
|
|||||||
@admin.register(EveAllianceInfo)
|
@admin.register(EveAllianceInfo)
|
||||||
class EveAllianceInfoAdmin(admin.ModelAdmin):
|
class EveAllianceInfoAdmin(admin.ModelAdmin):
|
||||||
search_fields = ['alliance_name']
|
search_fields = ['alliance_name']
|
||||||
list_display = ('alliance_name',)
|
list_display = ('alliance_name',)
|
||||||
ordering = ('alliance_name',)
|
ordering = ('alliance_name',)
|
||||||
|
|
||||||
def has_change_permission(self, request, obj=None):
|
def has_change_permission(self, request, obj=None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -129,9 +129,9 @@ class EveAllianceInfoAdmin(admin.ModelAdmin):
|
|||||||
@admin.register(EveCharacter)
|
@admin.register(EveCharacter)
|
||||||
class EveCharacterAdmin(admin.ModelAdmin):
|
class EveCharacterAdmin(admin.ModelAdmin):
|
||||||
search_fields = [
|
search_fields = [
|
||||||
'character_name',
|
'character_name',
|
||||||
'corporation_name',
|
'corporation_name',
|
||||||
'alliance_name',
|
'alliance_name',
|
||||||
'character_ownership__user__username'
|
'character_ownership__user__username'
|
||||||
]
|
]
|
||||||
list_display = (
|
list_display = (
|
||||||
@ -141,10 +141,10 @@ class EveCharacterAdmin(admin.ModelAdmin):
|
|||||||
'character_ownership', 'character_ownership__user__profile__main_character'
|
'character_ownership', 'character_ownership__user__profile__main_character'
|
||||||
)
|
)
|
||||||
list_filter = (
|
list_filter = (
|
||||||
'corporation_name',
|
'corporation_name',
|
||||||
'alliance_name',
|
'alliance_name',
|
||||||
(
|
(
|
||||||
'character_ownership__user__profile__main_character',
|
'character_ownership__user__profile__main_character',
|
||||||
admin.RelatedOnlyFieldListFilter
|
admin.RelatedOnlyFieldListFilter
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -44,7 +44,7 @@ class AutogroupsConfigManagerTestCase(TestCase):
|
|||||||
with patch('.models.AutogroupsConfig.update_group_membership_for_user') \
|
with patch('.models.AutogroupsConfig.update_group_membership_for_user') \
|
||||||
as update_group_membership_for_user:
|
as update_group_membership_for_user:
|
||||||
AutogroupsConfig.objects.update_groups_for_user(
|
AutogroupsConfig.objects.update_groups_for_user(
|
||||||
user=member,
|
user=member,
|
||||||
state=member.profile.state
|
state=member.profile.state
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -52,8 +52,8 @@ class AutogroupsConfigTestCase(TestCase):
|
|||||||
@patch('.models.AutogroupsConfig.update_alliance_group_membership')
|
@patch('.models.AutogroupsConfig.update_alliance_group_membership')
|
||||||
@patch('.models.AutogroupsConfig.update_corp_group_membership')
|
@patch('.models.AutogroupsConfig.update_corp_group_membership')
|
||||||
def test_update_group_membership_for_user(
|
def test_update_group_membership_for_user(
|
||||||
self,
|
self,
|
||||||
update_corp,
|
update_corp,
|
||||||
update_alliance
|
update_alliance
|
||||||
):
|
):
|
||||||
agc = AutogroupsConfig.objects.create()
|
agc = AutogroupsConfig.objects.create()
|
||||||
@ -123,9 +123,9 @@ class AutogroupsConfigTestCase(TestCase):
|
|||||||
alliance_ticker='alliance_ticker',
|
alliance_ticker='alliance_ticker',
|
||||||
executor_corp_id='2345'
|
executor_corp_id='2345'
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_create_alliance.side_effect = mock_create_alliance_side_effect
|
mock_create_alliance.side_effect = mock_create_alliance_side_effect
|
||||||
|
|
||||||
obj = AutogroupsConfig.objects.create(alliance_groups=True)
|
obj = AutogroupsConfig.objects.create(alliance_groups=True)
|
||||||
obj.states.add(AuthUtils.get_member_state())
|
obj.states.add(AuthUtils.get_member_state())
|
||||||
char = EveCharacter.objects.create(
|
char = EveCharacter.objects.create(
|
||||||
@ -140,7 +140,7 @@ class AutogroupsConfigTestCase(TestCase):
|
|||||||
self.member.profile.main_character = char
|
self.member.profile.main_character = char
|
||||||
self.member.profile.save()
|
self.member.profile.save()
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
obj.update_alliance_group_membership(self.member)
|
obj.update_alliance_group_membership(self.member)
|
||||||
|
|
||||||
group = obj.get_alliance_group(self.alliance)
|
group = obj.get_alliance_group(self.alliance)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# this package generates profile URL for eve entities
|
# this package generates profile URL for eve entities
|
||||||
# on 3rd party websites like evewho and zKillboard
|
# on 3rd party websites like evewho and zKillboard
|
||||||
#
|
#
|
||||||
# It contains of modules for views and templatetags for templates
|
# It contains of modules for views and templatetags for templates
|
||||||
|
|||||||
@ -3,9 +3,9 @@
|
|||||||
from urllib.parse import urljoin, quote
|
from urllib.parse import urljoin, quote
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
_ESI_CATEGORY_ALLIANCE,
|
_ESI_CATEGORY_ALLIANCE,
|
||||||
_ESI_CATEGORY_CORPORATION,
|
_ESI_CATEGORY_CORPORATION,
|
||||||
_ESI_CATEGORY_REGION,
|
_ESI_CATEGORY_REGION,
|
||||||
_ESI_CATEGORY_SOLARSYSTEM
|
_ESI_CATEGORY_SOLARSYSTEM
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,28 +15,28 @@ _BASE_URL = 'http://evemaps.dotlan.net'
|
|||||||
|
|
||||||
def _build_url(category: str, name: str) -> str:
|
def _build_url(category: str, name: str) -> str:
|
||||||
"""return url to profile page for an eve entity"""
|
"""return url to profile page for an eve entity"""
|
||||||
|
|
||||||
if category == _ESI_CATEGORY_ALLIANCE:
|
if category == _ESI_CATEGORY_ALLIANCE:
|
||||||
partial = 'alliance'
|
partial = 'alliance'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_CORPORATION:
|
elif category == _ESI_CATEGORY_CORPORATION:
|
||||||
partial = 'corp'
|
partial = 'corp'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_REGION:
|
elif category == _ESI_CATEGORY_REGION:
|
||||||
partial = 'map'
|
partial = 'map'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_SOLARSYSTEM:
|
elif category == _ESI_CATEGORY_SOLARSYSTEM:
|
||||||
partial = 'system'
|
partial = 'system'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Not implemented yet for category:" + category
|
"Not implemented yet for category:" + category
|
||||||
)
|
)
|
||||||
|
|
||||||
url = urljoin(
|
url = urljoin(
|
||||||
_BASE_URL,
|
_BASE_URL,
|
||||||
'{}/{}'.format(partial, quote(str(name).replace(" ", "_")))
|
'{}/{}'.format(partial, quote(str(name).replace(" ", "_")))
|
||||||
|
|
||||||
)
|
)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
from . import (
|
from . import (
|
||||||
_ESI_CATEGORY_ALLIANCE,
|
_ESI_CATEGORY_ALLIANCE,
|
||||||
_ESI_CATEGORY_CHARACTER,
|
_ESI_CATEGORY_CHARACTER,
|
||||||
_ESI_CATEGORY_CORPORATION,
|
_ESI_CATEGORY_CORPORATION,
|
||||||
_ESI_CATEGORY_INVENTORYTYPE
|
_ESI_CATEGORY_INVENTORYTYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ _EVE_IMAGE_SERVER_URL = 'https://images.evetech.net'
|
|||||||
_DEFAULT_IMAGE_SIZE = 32
|
_DEFAULT_IMAGE_SIZE = 32
|
||||||
|
|
||||||
|
|
||||||
def _eve_entity_image_url(
|
def _eve_entity_image_url(
|
||||||
category: str,
|
category: str,
|
||||||
entity_id: int,
|
entity_id: int,
|
||||||
size: int = 32,
|
size: int = 32,
|
||||||
@ -19,7 +19,7 @@ def _eve_entity_image_url(
|
|||||||
) -> str:
|
) -> str:
|
||||||
"""returns image URL for an Eve Online ID.
|
"""returns image URL for an Eve Online ID.
|
||||||
Supported categories: alliance, corporation, character, inventory_type
|
Supported categories: alliance, corporation, character, inventory_type
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
- category: category of the ID, see ESI category constants
|
- category: category of the ID, see ESI category constants
|
||||||
- entity_id: Eve ID of the entity
|
- entity_id: Eve ID of the entity
|
||||||
@ -33,7 +33,7 @@ def _eve_entity_image_url(
|
|||||||
Exceptions:
|
Exceptions:
|
||||||
- Throws ValueError on invalid input
|
- Throws ValueError on invalid input
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# input validations
|
# input validations
|
||||||
categories = {
|
categories = {
|
||||||
_ESI_CATEGORY_ALLIANCE: {
|
_ESI_CATEGORY_ALLIANCE: {
|
||||||
@ -54,15 +54,15 @@ def _eve_entity_image_url(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tenants = ['tranquility', 'singularity']
|
tenants = ['tranquility', 'singularity']
|
||||||
|
|
||||||
if not entity_id:
|
if not entity_id:
|
||||||
raise ValueError('Invalid entity_id: {}'.format(entity_id))
|
raise ValueError('Invalid entity_id: {}'.format(entity_id))
|
||||||
else:
|
else:
|
||||||
entity_id = int(entity_id)
|
entity_id = int(entity_id)
|
||||||
|
|
||||||
if not size or size < 32 or size > 1024 or (size & (size - 1) != 0):
|
if not size or size < 32 or size > 1024 or (size & (size - 1) != 0):
|
||||||
raise ValueError('Invalid size: {}'.format(size))
|
raise ValueError('Invalid size: {}'.format(size))
|
||||||
|
|
||||||
if category not in categories:
|
if category not in categories:
|
||||||
raise ValueError('Invalid category {}'.format(category))
|
raise ValueError('Invalid category {}'.format(category))
|
||||||
else:
|
else:
|
||||||
@ -79,7 +79,7 @@ def _eve_entity_image_url(
|
|||||||
|
|
||||||
if tenant and tenant not in tenants:
|
if tenant and tenant not in tenants:
|
||||||
raise ValueError('Invalid tenant {}'.format(tenant))
|
raise ValueError('Invalid tenant {}'.format(tenant))
|
||||||
|
|
||||||
# compose result URL
|
# compose result URL
|
||||||
result = '{}/{}/{}/{}?size={}'.format(
|
result = '{}/{}/{}/{}?size={}'.format(
|
||||||
_EVE_IMAGE_SERVER_URL,
|
_EVE_IMAGE_SERVER_URL,
|
||||||
@ -90,7 +90,7 @@ def _eve_entity_image_url(
|
|||||||
)
|
)
|
||||||
if tenant:
|
if tenant:
|
||||||
result += '&tenant={}'.format(tenant)
|
result += '&tenant={}'.format(tenant)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,9 +3,9 @@
|
|||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
_ESI_CATEGORY_ALLIANCE,
|
_ESI_CATEGORY_ALLIANCE,
|
||||||
_ESI_CATEGORY_CORPORATION,
|
_ESI_CATEGORY_CORPORATION,
|
||||||
_ESI_CATEGORY_CHARACTER,
|
_ESI_CATEGORY_CHARACTER,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -14,21 +14,21 @@ _BASE_URL = 'https://evewho.com'
|
|||||||
|
|
||||||
def _build_url(category: str, eve_id: int) -> str:
|
def _build_url(category: str, eve_id: int) -> str:
|
||||||
"""return url to profile page for an eve entity"""
|
"""return url to profile page for an eve entity"""
|
||||||
|
|
||||||
if category == _ESI_CATEGORY_ALLIANCE:
|
if category == _ESI_CATEGORY_ALLIANCE:
|
||||||
partial = 'alliance'
|
partial = 'alliance'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_CORPORATION:
|
elif category == _ESI_CATEGORY_CORPORATION:
|
||||||
partial = 'corporation'
|
partial = 'corporation'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_CHARACTER:
|
elif category == _ESI_CATEGORY_CHARACTER:
|
||||||
partial = 'character'
|
partial = 'character'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Not implemented yet for category:" + category
|
"Not implemented yet for category:" + category
|
||||||
)
|
)
|
||||||
|
|
||||||
url = urljoin(
|
url = urljoin(
|
||||||
_BASE_URL,
|
_BASE_URL,
|
||||||
'{}/{}'.format(partial, int(eve_id))
|
'{}/{}'.format(partial, int(eve_id))
|
||||||
|
|||||||
@ -12,12 +12,12 @@ class TestEveWho(TestCase):
|
|||||||
evewho.alliance_url(12345678),
|
evewho.alliance_url(12345678),
|
||||||
'https://evewho.com/alliance/12345678'
|
'https://evewho.com/alliance/12345678'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_corporation_url(self):
|
def test_corporation_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evewho.corporation_url(12345678),
|
evewho.corporation_url(12345678),
|
||||||
'https://evewho.com/corporation/12345678'
|
'https://evewho.com/corporation/12345678'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_character_url(self):
|
def test_character_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -49,7 +49,7 @@ class TestDotlan(TestCase):
|
|||||||
dotlan.region_url('Black Rise'),
|
dotlan.region_url('Black Rise'),
|
||||||
'http://evemaps.dotlan.net/map/Black_Rise'
|
'http://evemaps.dotlan.net/map/Black_Rise'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_solar_system_url(self):
|
def test_solar_system_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
dotlan.solar_system_url('Jita'),
|
dotlan.solar_system_url('Jita'),
|
||||||
@ -69,14 +69,14 @@ class TestZkillboard(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
zkillboard.corporation_url(12345678),
|
zkillboard.corporation_url(12345678),
|
||||||
'https://zkillboard.com/corporation/12345678/'
|
'https://zkillboard.com/corporation/12345678/'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_character_url(self):
|
def test_character_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
zkillboard.character_url(12345678),
|
zkillboard.character_url(12345678),
|
||||||
'https://zkillboard.com/character/12345678/'
|
'https://zkillboard.com/character/12345678/'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_region_url(self):
|
def test_region_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -93,34 +93,34 @@ class TestZkillboard(TestCase):
|
|||||||
|
|
||||||
class TestEveImageServer(TestCase):
|
class TestEveImageServer(TestCase):
|
||||||
"""unit test for eveimageserver"""
|
"""unit test for eveimageserver"""
|
||||||
|
|
||||||
def test_sizes(self):
|
def test_sizes(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42),
|
eveimageserver._eve_entity_image_url('character', 42),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=32'
|
'https://images.evetech.net/characters/42/portrait?size=32'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=32),
|
eveimageserver._eve_entity_image_url('character', 42, size=32),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=32'
|
'https://images.evetech.net/characters/42/portrait?size=32'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=64),
|
eveimageserver._eve_entity_image_url('character', 42, size=64),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=64'
|
'https://images.evetech.net/characters/42/portrait?size=64'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=128),
|
eveimageserver._eve_entity_image_url('character', 42, size=128),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=128'
|
'https://images.evetech.net/characters/42/portrait?size=128'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=256),
|
eveimageserver._eve_entity_image_url('character', 42, size=256),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=256'
|
'https://images.evetech.net/characters/42/portrait?size=256'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=512),
|
eveimageserver._eve_entity_image_url('character', 42, size=512),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=512'
|
'https://images.evetech.net/characters/42/portrait?size=512'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=1024),
|
eveimageserver._eve_entity_image_url('character', 42, size=1024),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=1024'
|
'https://images.evetech.net/characters/42/portrait?size=1024'
|
||||||
)
|
)
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
@ -128,10 +128,10 @@ class TestEveImageServer(TestCase):
|
|||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
eveimageserver._eve_entity_image_url('corporation', 42, size=0)
|
eveimageserver._eve_entity_image_url('corporation', 42, size=0)
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
eveimageserver._eve_entity_image_url('corporation', 42, size=31)
|
eveimageserver._eve_entity_image_url('corporation', 42, size=31)
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
eveimageserver._eve_entity_image_url('corporation', 42, size=1025)
|
eveimageserver._eve_entity_image_url('corporation', 42, size=1025)
|
||||||
|
|
||||||
@ -141,28 +141,28 @@ class TestEveImageServer(TestCase):
|
|||||||
|
|
||||||
def test_variant(self):
|
def test_variant(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, variant='portrait'),
|
eveimageserver._eve_entity_image_url('character', 42, variant='portrait'),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=32'
|
'https://images.evetech.net/characters/42/portrait?size=32'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('alliance', 42, variant='logo'),
|
eveimageserver._eve_entity_image_url('alliance', 42, variant='logo'),
|
||||||
'https://images.evetech.net/alliances/42/logo?size=32'
|
'https://images.evetech.net/alliances/42/logo?size=32'
|
||||||
)
|
)
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
eveimageserver._eve_entity_image_url('character', 42, variant='logo')
|
eveimageserver._eve_entity_image_url('character', 42, variant='logo')
|
||||||
|
|
||||||
|
|
||||||
def test_alliance(self):
|
def test_alliance(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('alliance', 42),
|
eveimageserver._eve_entity_image_url('alliance', 42),
|
||||||
'https://images.evetech.net/alliances/42/logo?size=32'
|
'https://images.evetech.net/alliances/42/logo?size=32'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('corporation', 42),
|
eveimageserver._eve_entity_image_url('corporation', 42),
|
||||||
'https://images.evetech.net/corporations/42/logo?size=32'
|
'https://images.evetech.net/corporations/42/logo?size=32'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42),
|
eveimageserver._eve_entity_image_url('character', 42),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=32'
|
'https://images.evetech.net/characters/42/portrait?size=32'
|
||||||
)
|
)
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
@ -171,16 +171,16 @@ class TestEveImageServer(TestCase):
|
|||||||
|
|
||||||
def test_tenants(self):
|
def test_tenants(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, tenant='tranquility'),
|
eveimageserver._eve_entity_image_url('character', 42, tenant='tranquility'),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=32&tenant=tranquility'
|
'https://images.evetech.net/characters/42/portrait?size=32&tenant=tranquility'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
eveimageserver._eve_entity_image_url('character', 42, tenant='singularity'),
|
eveimageserver._eve_entity_image_url('character', 42, tenant='singularity'),
|
||||||
'https://images.evetech.net/characters/42/portrait?size=32&tenant=singularity'
|
'https://images.evetech.net/characters/42/portrait?size=32&tenant=singularity'
|
||||||
)
|
)
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
eveimageserver._eve_entity_image_url('character', 42, tenant='xxx')
|
eveimageserver._eve_entity_image_url('character', 42, tenant='xxx')
|
||||||
|
|
||||||
def test_alliance_logo_url(self):
|
def test_alliance_logo_url(self):
|
||||||
expected = 'https://images.evetech.net/alliances/42/logo?size=128'
|
expected = 'https://images.evetech.net/alliances/42/logo?size=128'
|
||||||
self.assertEqual(eveimageserver.alliance_logo_url(42, 128), expected)
|
self.assertEqual(eveimageserver.alliance_logo_url(42, 128), expected)
|
||||||
|
|||||||
@ -38,15 +38,15 @@ class TestTemplateTags(TestCase):
|
|||||||
member_count=42,
|
member_count=42,
|
||||||
alliance=self.my_alliance
|
alliance=self.my_alliance
|
||||||
)
|
)
|
||||||
|
|
||||||
self.my_region_id = 8001
|
self.my_region_id = 8001
|
||||||
self.my_region_name = 'Southpark'
|
self.my_region_name = 'Southpark'
|
||||||
|
|
||||||
self.my_solar_system_id = 9001
|
self.my_solar_system_id = 9001
|
||||||
self.my_solar_system_name = 'Gotham'
|
self.my_solar_system_name = 'Gotham'
|
||||||
|
|
||||||
|
|
||||||
def test_evewho_character_url(self):
|
|
||||||
|
def test_evewho_character_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.evewho_character_url(self.my_character),
|
evelinks.evewho_character_url(self.my_character),
|
||||||
evewho.character_url(self.my_character.character_id),
|
evewho.character_url(self.my_character.character_id),
|
||||||
@ -59,9 +59,9 @@ class TestTemplateTags(TestCase):
|
|||||||
evelinks.evewho_character_url(self.my_character.character_id),
|
evelinks.evewho_character_url(self.my_character.character_id),
|
||||||
evewho.character_url(self.my_character.character_id),
|
evewho.character_url(self.my_character.character_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_evewho_corporation_url(self):
|
def test_evewho_corporation_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.evewho_corporation_url(self.my_character),
|
evelinks.evewho_corporation_url(self.my_character),
|
||||||
evewho.corporation_url(self.my_character.corporation_id),
|
evewho.corporation_url(self.my_character.corporation_id),
|
||||||
@ -80,7 +80,7 @@ class TestTemplateTags(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_evewho_alliance_url(self):
|
def test_evewho_alliance_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.evewho_alliance_url(self.my_character),
|
evelinks.evewho_alliance_url(self.my_character),
|
||||||
evewho.alliance_url(self.my_character.alliance_id),
|
evewho.alliance_url(self.my_character.alliance_id),
|
||||||
@ -100,12 +100,12 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.evewho_alliance_url(self.my_character.alliance_id),
|
evelinks.evewho_alliance_url(self.my_character.alliance_id),
|
||||||
evewho.alliance_url(self.my_character.alliance_id),
|
evewho.alliance_url(self.my_character.alliance_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# dotlan
|
# dotlan
|
||||||
|
|
||||||
def test_dotlan_corporation_url(self):
|
def test_dotlan_corporation_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_corporation_url(self.my_character),
|
evelinks.dotlan_corporation_url(self.my_character),
|
||||||
dotlan.corporation_url(self.my_character.corporation_name),
|
dotlan.corporation_url(self.my_character.corporation_name),
|
||||||
@ -121,10 +121,10 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_corporation_url(self.my_character.corporation_name),
|
evelinks.dotlan_corporation_url(self.my_character.corporation_name),
|
||||||
dotlan.corporation_url(self.my_character.corporation_name),
|
dotlan.corporation_url(self.my_character.corporation_name),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_dotlan_alliance_url(self):
|
def test_dotlan_alliance_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_alliance_url(self.my_character),
|
evelinks.dotlan_alliance_url(self.my_character),
|
||||||
dotlan.alliance_url(self.my_character.alliance_name),
|
dotlan.alliance_url(self.my_character.alliance_name),
|
||||||
@ -144,32 +144,32 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_alliance_url(self.my_character.alliance_name),
|
evelinks.dotlan_alliance_url(self.my_character.alliance_name),
|
||||||
dotlan.alliance_url(self.my_character.alliance_name),
|
dotlan.alliance_url(self.my_character.alliance_name),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_dotlan_region_url(self):
|
def test_dotlan_region_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_region_url(self.my_region_name),
|
evelinks.dotlan_region_url(self.my_region_name),
|
||||||
dotlan.region_url(self.my_region_name),
|
dotlan.region_url(self.my_region_name),
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_region_url(None),
|
evelinks.dotlan_region_url(None),
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_dotlan_solar_system_url(self):
|
def test_dotlan_solar_system_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_solar_system_url(self.my_solar_system_name),
|
evelinks.dotlan_solar_system_url(self.my_solar_system_name),
|
||||||
dotlan.solar_system_url(self.my_solar_system_name),
|
dotlan.solar_system_url(self.my_solar_system_name),
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.dotlan_solar_system_url(None),
|
evelinks.dotlan_solar_system_url(None),
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# zkillboard
|
# zkillboard
|
||||||
|
|
||||||
def test_zkillboard_character_url(self):
|
def test_zkillboard_character_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_character_url(self.my_character),
|
evelinks.zkillboard_character_url(self.my_character),
|
||||||
zkillboard.character_url(self.my_character.character_id),
|
zkillboard.character_url(self.my_character.character_id),
|
||||||
@ -182,9 +182,9 @@ class TestTemplateTags(TestCase):
|
|||||||
evelinks.zkillboard_character_url(self.my_character.character_id),
|
evelinks.zkillboard_character_url(self.my_character.character_id),
|
||||||
zkillboard.character_url(self.my_character.character_id),
|
zkillboard.character_url(self.my_character.character_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_zkillboard_corporation_url(self):
|
def test_zkillboard_corporation_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_corporation_url(self.my_character),
|
evelinks.zkillboard_corporation_url(self.my_character),
|
||||||
zkillboard.corporation_url(self.my_character.corporation_id),
|
zkillboard.corporation_url(self.my_character.corporation_id),
|
||||||
@ -200,10 +200,10 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_corporation_url(self.my_character.corporation_id),
|
evelinks.zkillboard_corporation_url(self.my_character.corporation_id),
|
||||||
zkillboard.corporation_url(self.my_character.corporation_id),
|
zkillboard.corporation_url(self.my_character.corporation_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_zkillboard_alliance_url(self):
|
def test_zkillboard_alliance_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_alliance_url(self.my_character),
|
evelinks.zkillboard_alliance_url(self.my_character),
|
||||||
zkillboard.alliance_url(self.my_character.alliance_id),
|
zkillboard.alliance_url(self.my_character.alliance_id),
|
||||||
@ -223,29 +223,29 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_alliance_url(self.my_character.alliance_id),
|
evelinks.zkillboard_alliance_url(self.my_character.alliance_id),
|
||||||
zkillboard.alliance_url(self.my_character.alliance_id),
|
zkillboard.alliance_url(self.my_character.alliance_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_zkillboard_region_url(self):
|
def test_zkillboard_region_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_region_url(self.my_region_id),
|
evelinks.zkillboard_region_url(self.my_region_id),
|
||||||
zkillboard.region_url(self.my_region_id),
|
zkillboard.region_url(self.my_region_id),
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_region_url(None),
|
evelinks.zkillboard_region_url(None),
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_zkillboard_solar_system_url(self):
|
def test_zkillboard_solar_system_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_solar_system_url(self.my_solar_system_id),
|
evelinks.zkillboard_solar_system_url(self.my_solar_system_id),
|
||||||
zkillboard.solar_system_url(self.my_solar_system_id),
|
zkillboard.solar_system_url(self.my_solar_system_id),
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.zkillboard_solar_system_url(None),
|
evelinks.zkillboard_solar_system_url(None),
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# image URLs
|
# image URLs
|
||||||
@ -254,12 +254,12 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.character_portrait_url(123),
|
evelinks.character_portrait_url(123),
|
||||||
EveCharacter.generic_portrait_url(123)
|
EveCharacter.generic_portrait_url(123)
|
||||||
|
|
||||||
),
|
),
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.character_portrait_url(123, 128),
|
evelinks.character_portrait_url(123, 128),
|
||||||
EveCharacter.generic_portrait_url(123, 128)
|
EveCharacter.generic_portrait_url(123, 128)
|
||||||
|
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.character_portrait_url(123, 99),
|
evelinks.character_portrait_url(123, 99),
|
||||||
@ -267,7 +267,7 @@ class TestTemplateTags(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.character_portrait_url(self.my_character),
|
evelinks.character_portrait_url(self.my_character),
|
||||||
self.my_character.portrait_url()
|
self.my_character.portrait_url()
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.character_portrait_url(None),
|
evelinks.character_portrait_url(None),
|
||||||
@ -286,7 +286,7 @@ class TestTemplateTags(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.corporation_logo_url(123, 99),
|
evelinks.corporation_logo_url(123, 99),
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.corporation_logo_url(self.my_corporation),
|
evelinks.corporation_logo_url(self.my_corporation),
|
||||||
@ -303,7 +303,7 @@ class TestTemplateTags(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
def test_alliance_logo_url(self):
|
def test_alliance_logo_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.alliance_logo_url(123),
|
evelinks.alliance_logo_url(123),
|
||||||
EveAllianceInfo.generic_logo_url(123)
|
EveAllianceInfo.generic_logo_url(123)
|
||||||
),
|
),
|
||||||
@ -314,7 +314,7 @@ class TestTemplateTags(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.alliance_logo_url(123, 99),
|
evelinks.alliance_logo_url(123, 99),
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
evelinks.alliance_logo_url(self.my_alliance),
|
evelinks.alliance_logo_url(self.my_alliance),
|
||||||
self.my_alliance.logo_url()
|
self.my_alliance.logo_url()
|
||||||
@ -338,10 +338,10 @@ class TestTemplateTags(TestCase):
|
|||||||
|
|
||||||
expected = eveimageserver.type_icon_url(123, 128)
|
expected = eveimageserver.type_icon_url(123, 128)
|
||||||
self.assertEqual(evelinks.type_icon_url(123, 128), expected)
|
self.assertEqual(evelinks.type_icon_url(123, 128), expected)
|
||||||
|
|
||||||
expected = ''
|
expected = ''
|
||||||
self.assertEqual(evelinks.type_icon_url(123, 99), expected)
|
self.assertEqual(evelinks.type_icon_url(123, 99), expected)
|
||||||
|
|
||||||
expected = ''
|
expected = ''
|
||||||
self.assertEqual(evelinks.type_icon_url(None), expected)
|
self.assertEqual(evelinks.type_icon_url(None), expected)
|
||||||
|
|
||||||
@ -351,9 +351,9 @@ class TestTemplateTags(TestCase):
|
|||||||
|
|
||||||
expected = eveimageserver.type_render_url(123, 128)
|
expected = eveimageserver.type_render_url(123, 128)
|
||||||
self.assertEqual(evelinks.type_render_url(123, 128), expected)
|
self.assertEqual(evelinks.type_render_url(123, 128), expected)
|
||||||
|
|
||||||
expected = ''
|
expected = ''
|
||||||
self.assertEqual(evelinks.type_render_url(123, 99), expected)
|
self.assertEqual(evelinks.type_render_url(123, 99), expected)
|
||||||
|
|
||||||
expected = ''
|
expected = ''
|
||||||
self.assertEqual(evelinks.type_render_url(None), expected)
|
self.assertEqual(evelinks.type_render_url(None), expected)
|
||||||
@ -3,10 +3,10 @@
|
|||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
_ESI_CATEGORY_ALLIANCE,
|
_ESI_CATEGORY_ALLIANCE,
|
||||||
_ESI_CATEGORY_CORPORATION,
|
_ESI_CATEGORY_CORPORATION,
|
||||||
_ESI_CATEGORY_CHARACTER,
|
_ESI_CATEGORY_CHARACTER,
|
||||||
_ESI_CATEGORY_REGION,
|
_ESI_CATEGORY_REGION,
|
||||||
_ESI_CATEGORY_SOLARSYSTEM
|
_ESI_CATEGORY_SOLARSYSTEM
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,11 +16,11 @@ _BASE_URL = 'https://zkillboard.com'
|
|||||||
|
|
||||||
def _build_url(category: str, eve_id: int) -> str:
|
def _build_url(category: str, eve_id: int) -> str:
|
||||||
"""return url to profile page for an eve entity"""
|
"""return url to profile page for an eve entity"""
|
||||||
|
|
||||||
if category == _ESI_CATEGORY_ALLIANCE:
|
if category == _ESI_CATEGORY_ALLIANCE:
|
||||||
partial = 'alliance'
|
partial = 'alliance'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_CORPORATION:
|
elif category == _ESI_CATEGORY_CORPORATION:
|
||||||
partial = 'corporation'
|
partial = 'corporation'
|
||||||
|
|
||||||
elif category == _ESI_CATEGORY_CHARACTER:
|
elif category == _ESI_CATEGORY_CHARACTER:
|
||||||
@ -31,12 +31,12 @@ def _build_url(category: str, eve_id: int) -> str:
|
|||||||
|
|
||||||
elif category == _ESI_CATEGORY_SOLARSYSTEM:
|
elif category == _ESI_CATEGORY_SOLARSYSTEM:
|
||||||
partial = 'system'
|
partial = 'system'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Not implemented yet for category:" + category
|
"Not implemented yet for category:" + category
|
||||||
)
|
)
|
||||||
|
|
||||||
url = urljoin(
|
url = urljoin(
|
||||||
_BASE_URL,
|
_BASE_URL,
|
||||||
'{}/{}/'.format(partial, int(eve_id))
|
'{}/{}/'.format(partial, int(eve_id))
|
||||||
|
|||||||
@ -51,7 +51,7 @@ class EveAllianceInfo(models.Model):
|
|||||||
) -> str:
|
) -> str:
|
||||||
"""image URL for the given alliance ID"""
|
"""image URL for the given alliance ID"""
|
||||||
return eveimageserver.alliance_logo_url(alliance_id, size)
|
return eveimageserver.alliance_logo_url(alliance_id, size)
|
||||||
|
|
||||||
def logo_url(self, size: int = _DEFAULT_IMAGE_SIZE) -> str:
|
def logo_url(self, size: int = _DEFAULT_IMAGE_SIZE) -> str:
|
||||||
"""image URL of this alliance"""
|
"""image URL of this alliance"""
|
||||||
return self.generic_logo_url(self.alliance_id, size)
|
return self.generic_logo_url(self.alliance_id, size)
|
||||||
@ -224,7 +224,7 @@ class EveCharacter(models.Model):
|
|||||||
def portrait_url_128(self) -> str:
|
def portrait_url_128(self) -> str:
|
||||||
"""image URL for this character"""
|
"""image URL for this character"""
|
||||||
return self.portrait_url(128)
|
return self.portrait_url(128)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def portrait_url_256(self) -> str:
|
def portrait_url_256(self) -> str:
|
||||||
"""image URL for this character"""
|
"""image URL for this character"""
|
||||||
@ -275,7 +275,7 @@ class EveCharacter(models.Model):
|
|||||||
def alliance_logo_url_128(self) -> str:
|
def alliance_logo_url_128(self) -> str:
|
||||||
"""image URL for alliance of this character or empty string"""
|
"""image URL for alliance of this character or empty string"""
|
||||||
return self.alliance_logo_url(128)
|
return self.alliance_logo_url(128)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def alliance_logo_url_256(self) -> str:
|
def alliance_logo_url_256(self) -> str:
|
||||||
"""image URL for alliance of this character or empty string"""
|
"""image URL for alliance of this character or empty string"""
|
||||||
|
|||||||
@ -159,7 +159,7 @@ class EveProvider(object):
|
|||||||
|
|
||||||
|
|
||||||
class EveSwaggerProvider(EveProvider):
|
class EveSwaggerProvider(EveProvider):
|
||||||
def __init__(self, token=None, adapter=None):
|
def __init__(self, token=None, adapter=None):
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
self._client = None
|
self._client = None
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|||||||
@ -40,7 +40,7 @@ def update_character(character_id):
|
|||||||
@shared_task
|
@shared_task
|
||||||
def run_model_update():
|
def run_model_update():
|
||||||
"""Update all alliances, corporations and characters from ESI"""
|
"""Update all alliances, corporations and characters from ESI"""
|
||||||
|
|
||||||
# update existing corp models
|
# update existing corp models
|
||||||
for corp in EveCorporationInfo.objects.all().values('corporation_id'):
|
for corp in EveCorporationInfo.objects.all().values('corporation_id'):
|
||||||
update_corp.apply_async(
|
update_corp.apply_async(
|
||||||
@ -54,7 +54,7 @@ def run_model_update():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# update existing character models
|
# update existing character models
|
||||||
character_ids = EveCharacter.objects.all().values_list('character_id', flat=True)
|
character_ids = EveCharacter.objects.all().values_list('character_id', flat=True)
|
||||||
for character_ids_chunk in chunks(character_ids, CHUNK_SIZE):
|
for character_ids_chunk in chunks(character_ids, CHUNK_SIZE):
|
||||||
affiliations_raw = providers.provider.client.Character\
|
affiliations_raw = providers.provider.client.Character\
|
||||||
.post_characters_affiliation(characters=character_ids_chunk).result()
|
.post_characters_affiliation(characters=character_ids_chunk).result()
|
||||||
@ -62,39 +62,39 @@ def run_model_update():
|
|||||||
.post_universe_names(ids=character_ids_chunk).result()
|
.post_universe_names(ids=character_ids_chunk).result()
|
||||||
|
|
||||||
affiliations = {
|
affiliations = {
|
||||||
affiliation.get('character_id'): affiliation
|
affiliation.get('character_id'): affiliation
|
||||||
for affiliation in affiliations_raw
|
for affiliation in affiliations_raw
|
||||||
}
|
}
|
||||||
# add character names to affiliations
|
# add character names to affiliations
|
||||||
for character in character_names:
|
for character in character_names:
|
||||||
character_id = character.get('id')
|
character_id = character.get('id')
|
||||||
if character_id in affiliations:
|
if character_id in affiliations:
|
||||||
affiliations[character_id]['name'] = character.get('name')
|
affiliations[character_id]['name'] = character.get('name')
|
||||||
|
|
||||||
# fetch current characters
|
# fetch current characters
|
||||||
characters = EveCharacter.objects.filter(character_id__in=character_ids_chunk)\
|
characters = EveCharacter.objects.filter(character_id__in=character_ids_chunk)\
|
||||||
.values('character_id', 'corporation_id', 'alliance_id', 'character_name')
|
.values('character_id', 'corporation_id', 'alliance_id', 'character_name')
|
||||||
|
|
||||||
for character in characters:
|
for character in characters:
|
||||||
character_id = character.get('character_id')
|
character_id = character.get('character_id')
|
||||||
if character_id in affiliations:
|
if character_id in affiliations:
|
||||||
affiliation = affiliations[character_id]
|
affiliation = affiliations[character_id]
|
||||||
|
|
||||||
corp_changed = (
|
corp_changed = (
|
||||||
character.get('corporation_id') != affiliation.get('corporation_id')
|
character.get('corporation_id') != affiliation.get('corporation_id')
|
||||||
)
|
)
|
||||||
|
|
||||||
alliance_id = character.get('alliance_id')
|
alliance_id = character.get('alliance_id')
|
||||||
if not alliance_id:
|
if not alliance_id:
|
||||||
alliance_id = None
|
alliance_id = None
|
||||||
alliance_changed = alliance_id != affiliation.get('alliance_id')
|
alliance_changed = alliance_id != affiliation.get('alliance_id')
|
||||||
|
|
||||||
name_changed = False
|
name_changed = False
|
||||||
fetched_name = affiliation.get('name', False)
|
fetched_name = affiliation.get('name', False)
|
||||||
if fetched_name:
|
if fetched_name:
|
||||||
name_changed = character.get('character_name') != fetched_name
|
name_changed = character.get('character_name') != fetched_name
|
||||||
|
|
||||||
if corp_changed or alliance_changed or name_changed:
|
if corp_changed or alliance_changed or name_changed:
|
||||||
update_character.apply_async(
|
update_character.apply_async(
|
||||||
args=[character.get('character_id')], priority=TASK_PRIORITY
|
args=[character.get('character_id')], priority=TASK_PRIORITY
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
# This module defines template tags for evelinks URLs and eve image URLs
|
# This module defines template tags for evelinks URLs and eve image URLs
|
||||||
#
|
#
|
||||||
# Many tags will work both with their respective eveonline object
|
# Many tags will work both with their respective eveonline object
|
||||||
# and their respective eve entity ID
|
# and their respective eve entity ID
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
# character URL on evewho: {{ my_character|evewho_character_url}}
|
# character URL on evewho: {{ my_character|evewho_character_url}}
|
||||||
# character URL on evewho: {{ 1456384556|evewho_character_url}}
|
# character URL on evewho: {{ 1456384556|evewho_character_url}}
|
||||||
#
|
#
|
||||||
# For more examples see examples.html
|
# For more examples see examples.html
|
||||||
#
|
#
|
||||||
# To add templatetags for additional providers just add the respective
|
# To add templatetags for additional providers just add the respective
|
||||||
# template functions and let them call the generic functions
|
# template functions and let them call the generic functions
|
||||||
|
|
||||||
@ -25,59 +25,59 @@ _DEFAULT_IMAGE_SIZE = 32
|
|||||||
# generic functions
|
# generic functions
|
||||||
|
|
||||||
def _generic_character_url(
|
def _generic_character_url(
|
||||||
provider: object,
|
provider: object,
|
||||||
obj_prop: str,
|
obj_prop: str,
|
||||||
eve_obj: EveCharacter
|
eve_obj: EveCharacter
|
||||||
) -> str:
|
) -> str:
|
||||||
"""returns character URL for given provider and object"""
|
"""returns character URL for given provider and object"""
|
||||||
my_func = getattr(provider, 'character_url')
|
my_func = getattr(provider, 'character_url')
|
||||||
if isinstance(eve_obj, EveCharacter):
|
if isinstance(eve_obj, EveCharacter):
|
||||||
return my_func(getattr(eve_obj, obj_prop))
|
return my_func(getattr(eve_obj, obj_prop))
|
||||||
|
|
||||||
elif eve_obj is None:
|
elif eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return my_func(eve_obj)
|
return my_func(eve_obj)
|
||||||
|
|
||||||
|
|
||||||
def _generic_corporation_url(
|
def _generic_corporation_url(
|
||||||
provider: object,
|
provider: object,
|
||||||
obj_prop: str,
|
obj_prop: str,
|
||||||
eve_obj: object
|
eve_obj: object
|
||||||
) -> str:
|
) -> str:
|
||||||
"""returns corporation URL for given provider and object"""
|
"""returns corporation URL for given provider and object"""
|
||||||
my_func = getattr(provider, 'corporation_url')
|
my_func = getattr(provider, 'corporation_url')
|
||||||
if isinstance(eve_obj, (EveCharacter, EveCorporationInfo)):
|
if isinstance(eve_obj, (EveCharacter, EveCorporationInfo)):
|
||||||
return my_func(getattr(eve_obj, obj_prop))
|
return my_func(getattr(eve_obj, obj_prop))
|
||||||
|
|
||||||
elif eve_obj is None:
|
elif eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return my_func(eve_obj)
|
return my_func(eve_obj)
|
||||||
|
|
||||||
|
|
||||||
def _generic_alliance_url(
|
def _generic_alliance_url(
|
||||||
provider: object,
|
provider: object,
|
||||||
obj_prop: str,
|
obj_prop: str,
|
||||||
eve_obj: object
|
eve_obj: object
|
||||||
) -> str:
|
) -> str:
|
||||||
"""returns alliance URL for given provider and object"""
|
"""returns alliance URL for given provider and object"""
|
||||||
my_func = getattr(provider, 'alliance_url')
|
my_func = getattr(provider, 'alliance_url')
|
||||||
|
|
||||||
if isinstance(eve_obj, EveCharacter):
|
if isinstance(eve_obj, EveCharacter):
|
||||||
if eve_obj.alliance_id:
|
if eve_obj.alliance_id:
|
||||||
return my_func(getattr(eve_obj, obj_prop))
|
return my_func(getattr(eve_obj, obj_prop))
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
elif isinstance(eve_obj, EveAllianceInfo):
|
elif isinstance(eve_obj, EveAllianceInfo):
|
||||||
return my_func(getattr(eve_obj, obj_prop))
|
return my_func(getattr(eve_obj, obj_prop))
|
||||||
|
|
||||||
elif eve_obj is None:
|
elif eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return my_func(eve_obj)
|
return my_func(eve_obj)
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ def _generic_evelinks_url(
|
|||||||
my_func = getattr(provider, provider_func)
|
my_func = getattr(provider, provider_func)
|
||||||
if eve_obj is None:
|
if eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return my_func(eve_obj)
|
return my_func(eve_obj)
|
||||||
|
|
||||||
@ -99,29 +99,29 @@ def _generic_evelinks_url(
|
|||||||
# evewho
|
# evewho
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def evewho_character_url(eve_obj: EveCharacter) -> str:
|
def evewho_character_url(eve_obj: EveCharacter) -> str:
|
||||||
"""generates an evewho URL for the given object
|
"""generates an evewho URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity IDs
|
Works with allianceauth.eveonline objects and eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_character_url(evewho, 'character_id', eve_obj)
|
return _generic_character_url(evewho, 'character_id', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def evewho_corporation_url(eve_obj: object) -> str:
|
def evewho_corporation_url(eve_obj: object) -> str:
|
||||||
"""generates an evewho URL for the given object
|
"""generates an evewho URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity IDs
|
Works with allianceauth.eveonline objects and eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_corporation_url(evewho, 'corporation_id', eve_obj)
|
return _generic_corporation_url(evewho, 'corporation_id', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def evewho_alliance_url(eve_obj: object) -> str:
|
def evewho_alliance_url(eve_obj: object) -> str:
|
||||||
"""generates an evewho URL for the given object
|
"""generates an evewho URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity IDs
|
Works with allianceauth.eveonline objects and eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_alliance_url(evewho, 'alliance_id', eve_obj)
|
return _generic_alliance_url(evewho, 'alliance_id', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@ -131,69 +131,69 @@ def evewho_alliance_url(eve_obj: object) -> str:
|
|||||||
def dotlan_corporation_url(eve_obj: object) -> str:
|
def dotlan_corporation_url(eve_obj: object) -> str:
|
||||||
"""generates a dotlan URL for the given object
|
"""generates a dotlan URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity names
|
Works with allianceauth.eveonline objects and eve entity names
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_corporation_url(dotlan, 'corporation_name', eve_obj)
|
return _generic_corporation_url(dotlan, 'corporation_name', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def dotlan_alliance_url(eve_obj: object) -> str:
|
def dotlan_alliance_url(eve_obj: object) -> str:
|
||||||
"""generates a dotlan URL for the given object
|
"""generates a dotlan URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity names
|
Works with allianceauth.eveonline objects and eve entity names
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_alliance_url(dotlan, 'alliance_name', eve_obj)
|
return _generic_alliance_url(dotlan, 'alliance_name', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def dotlan_region_url(eve_obj: object) -> str:
|
def dotlan_region_url(eve_obj: object) -> str:
|
||||||
"""generates a dotlan URL for the given object
|
"""generates a dotlan URL for the given object
|
||||||
Works with eve entity names
|
Works with eve entity names
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_evelinks_url(dotlan, 'region_url', eve_obj)
|
return _generic_evelinks_url(dotlan, 'region_url', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def dotlan_solar_system_url(eve_obj: object) -> str:
|
def dotlan_solar_system_url(eve_obj: object) -> str:
|
||||||
"""generates a dotlan URL for the given object
|
"""generates a dotlan URL for the given object
|
||||||
Works with eve entity names
|
Works with eve entity names
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_evelinks_url(dotlan, 'solar_system_url', eve_obj)
|
return _generic_evelinks_url(dotlan, 'solar_system_url', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
# zkillboard
|
# zkillboard
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def zkillboard_character_url(eve_obj: EveCharacter) -> str:
|
def zkillboard_character_url(eve_obj: EveCharacter) -> str:
|
||||||
"""generates a zkillboard URL for the given object
|
"""generates a zkillboard URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity IDs
|
Works with allianceauth.eveonline objects and eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_character_url(zkillboard, 'character_id', eve_obj)
|
return _generic_character_url(zkillboard, 'character_id', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def zkillboard_corporation_url(eve_obj: object) -> str:
|
def zkillboard_corporation_url(eve_obj: object) -> str:
|
||||||
"""generates a zkillboard URL for the given object
|
"""generates a zkillboard URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity IDs
|
Works with allianceauth.eveonline objects and eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_corporation_url(zkillboard, 'corporation_id', eve_obj)
|
return _generic_corporation_url(zkillboard, 'corporation_id', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def zkillboard_alliance_url(eve_obj: object) -> str:
|
def zkillboard_alliance_url(eve_obj: object) -> str:
|
||||||
"""generates a zkillboard URL for the given object
|
"""generates a zkillboard URL for the given object
|
||||||
Works with allianceauth.eveonline objects and eve entity IDs
|
Works with allianceauth.eveonline objects and eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
return _generic_alliance_url(zkillboard, 'alliance_id', eve_obj)
|
return _generic_alliance_url(zkillboard, 'alliance_id', eve_obj)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def zkillboard_region_url(eve_obj: object) -> str:
|
def zkillboard_region_url(eve_obj: object) -> str:
|
||||||
"""generates a zkillboard URL for the given object
|
"""generates a zkillboard URL for the given object
|
||||||
Works with eve entity IDs
|
Works with eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
@ -202,7 +202,7 @@ def zkillboard_region_url(eve_obj: object) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def zkillboard_solar_system_url(eve_obj: object) -> str:
|
def zkillboard_solar_system_url(eve_obj: object) -> str:
|
||||||
"""generates zkillboard URL for the given object
|
"""generates zkillboard URL for the given object
|
||||||
Works with eve entity IDs
|
Works with eve entity IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
@ -214,20 +214,20 @@ def zkillboard_solar_system_url(eve_obj: object) -> str:
|
|||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def character_portrait_url(
|
def character_portrait_url(
|
||||||
eve_obj: object,
|
eve_obj: object,
|
||||||
size: int = _DEFAULT_IMAGE_SIZE
|
size: int = _DEFAULT_IMAGE_SIZE
|
||||||
) -> str:
|
) -> str:
|
||||||
"""generates an image URL for the given object
|
"""generates an image URL for the given object
|
||||||
Works with EveCharacter objects or character IDs
|
Works with EveCharacter objects or character IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
if isinstance(eve_obj, EveCharacter):
|
if isinstance(eve_obj, EveCharacter):
|
||||||
return eve_obj.portrait_url(size)
|
return eve_obj.portrait_url(size)
|
||||||
|
|
||||||
elif eve_obj is None:
|
elif eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return EveCharacter.generic_portrait_url(eve_obj, size)
|
return EveCharacter.generic_portrait_url(eve_obj, size)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -236,23 +236,23 @@ def character_portrait_url(
|
|||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def corporation_logo_url(
|
def corporation_logo_url(
|
||||||
eve_obj: object,
|
eve_obj: object,
|
||||||
size: int = _DEFAULT_IMAGE_SIZE
|
size: int = _DEFAULT_IMAGE_SIZE
|
||||||
) -> str:
|
) -> str:
|
||||||
"""generates image URL for the given object
|
"""generates image URL for the given object
|
||||||
Works with EveCharacter, EveCorporationInfo objects or corporation IDs
|
Works with EveCharacter, EveCorporationInfo objects or corporation IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
if isinstance(eve_obj, EveCorporationInfo):
|
if isinstance(eve_obj, EveCorporationInfo):
|
||||||
return eve_obj.logo_url(size)
|
return eve_obj.logo_url(size)
|
||||||
|
|
||||||
elif isinstance(eve_obj, EveCharacter):
|
elif isinstance(eve_obj, EveCharacter):
|
||||||
return eve_obj.corporation_logo_url(size)
|
return eve_obj.corporation_logo_url(size)
|
||||||
|
|
||||||
elif eve_obj is None:
|
elif eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return EveCorporationInfo.generic_logo_url(eve_obj, size)
|
return EveCorporationInfo.generic_logo_url(eve_obj, size)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -261,23 +261,23 @@ def corporation_logo_url(
|
|||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def alliance_logo_url(
|
def alliance_logo_url(
|
||||||
eve_obj: object,
|
eve_obj: object,
|
||||||
size: int = _DEFAULT_IMAGE_SIZE
|
size: int = _DEFAULT_IMAGE_SIZE
|
||||||
) -> str:
|
) -> str:
|
||||||
"""generates image URL for the given object
|
"""generates image URL for the given object
|
||||||
Works with EveCharacter, EveAllianceInfo objects or alliance IDs
|
Works with EveCharacter, EveAllianceInfo objects or alliance IDs
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
if isinstance(eve_obj, EveAllianceInfo):
|
if isinstance(eve_obj, EveAllianceInfo):
|
||||||
return eve_obj.logo_url(size)
|
return eve_obj.logo_url(size)
|
||||||
|
|
||||||
elif isinstance(eve_obj, EveCharacter):
|
elif isinstance(eve_obj, EveCharacter):
|
||||||
return eve_obj.alliance_logo_url(size)
|
return eve_obj.alliance_logo_url(size)
|
||||||
|
|
||||||
elif eve_obj is None:
|
elif eve_obj is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return EveAllianceInfo.generic_logo_url(eve_obj, size)
|
return EveAllianceInfo.generic_logo_url(eve_obj, size)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -286,10 +286,10 @@ def alliance_logo_url(
|
|||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def type_icon_url(
|
def type_icon_url(
|
||||||
type_id: int,
|
type_id: int,
|
||||||
size: int = _DEFAULT_IMAGE_SIZE
|
size: int = _DEFAULT_IMAGE_SIZE
|
||||||
) -> str:
|
) -> str:
|
||||||
"""generates a icon image URL for the given type ID
|
"""generates a icon image URL for the given type ID
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
@ -300,10 +300,10 @@ def type_icon_url(
|
|||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def type_render_url(
|
def type_render_url(
|
||||||
type_id: int,
|
type_id: int,
|
||||||
size: int = _DEFAULT_IMAGE_SIZE
|
size: int = _DEFAULT_IMAGE_SIZE
|
||||||
) -> str:
|
) -> str:
|
||||||
"""generates a render image URL for the given type ID
|
"""generates a render image URL for the given type ID
|
||||||
Returns URL or empty string
|
Returns URL or empty string
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<!-- This is an example template for the evelinks template tags
|
<!-- This is an example template for the evelinks template tags
|
||||||
|
|
||||||
Needs to be called with a context containing three objects:
|
Needs to be called with a context containing three objects:
|
||||||
|
|
||||||
@ -18,15 +18,15 @@ Needs to be called with a context containing three objects:
|
|||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<h1 class="page-header text-center">Evelinks templatetags examples</h1>
|
<h1 class="page-header text-center">Evelinks templatetags examples</h1>
|
||||||
<div class="col-lg-12 container">
|
<div class="col-lg-12 container">
|
||||||
|
|
||||||
<h2>profile URLs</h2>
|
<h2>profile URLs</h2>
|
||||||
|
|
||||||
<div class="rows">
|
<div class="rows">
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h3>evewho</h3>
|
<h3>evewho</h3>
|
||||||
<p><a href="{{ my_character|evewho_character_url}}">character from character object</a></p>
|
<p><a href="{{ my_character|evewho_character_url}}">character from character object</a></p>
|
||||||
<p><a href="{{ my_corporation|evewho_corporation_url}}">corporation form corporation object</a></p>
|
<p><a href="{{ my_corporation|evewho_corporation_url}}">corporation form corporation object</a></p>
|
||||||
<p><a href="{{ my_character|evewho_corporation_url}}">corporation from charachter object</a></p>
|
<p><a href="{{ my_character|evewho_corporation_url}}">corporation from charachter object</a></p>
|
||||||
<p><a href="{{ my_alliance|evewho_alliance_url}}">alliance from alliance object</a></p>
|
<p><a href="{{ my_alliance|evewho_alliance_url}}">alliance from alliance object</a></p>
|
||||||
<p><a href="{{ my_character|evewho_alliance_url}}">alliance from character object</a></p>
|
<p><a href="{{ my_character|evewho_alliance_url}}">alliance from character object</a></p>
|
||||||
@ -42,23 +42,23 @@ Needs to be called with a context containing three objects:
|
|||||||
<p><a href="{{ 'Tama'|dotlan_solar_system_url}}">solar system from name string</a></p>
|
<p><a href="{{ 'Tama'|dotlan_solar_system_url}}">solar system from name string</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h3>zkillboard</h3>
|
<h3>zkillboard</h3>
|
||||||
<p><a href="{{ my_character|zkillboard_character_url}}">character from character object</a></p>
|
<p><a href="{{ my_character|zkillboard_character_url}}">character from character object</a></p>
|
||||||
<p><a href="{{ my_character|zkillboard_corporation_url}}">corporation from character object</a></p>
|
<p><a href="{{ my_character|zkillboard_corporation_url}}">corporation from character object</a></p>
|
||||||
<p><a href="{{ my_corporation|zkillboard_corporation_url}}">corporation form corporation object</a></p>
|
<p><a href="{{ my_corporation|zkillboard_corporation_url}}">corporation form corporation object</a></p>
|
||||||
<p><a href="{{ my_character|zkillboard_alliance_url}}">alliance from character object</a></p>
|
<p><a href="{{ my_character|zkillboard_alliance_url}}">alliance from character object</a></p>
|
||||||
<p><a href="{{ my_alliance|zkillboard_alliance_url}}">alliance from alliance object</a></p>
|
<p><a href="{{ my_alliance|zkillboard_alliance_url}}">alliance from alliance object</a></p>
|
||||||
<p><a href="{{ 10000069|zkillboard_region_url}}">region from ID</a></p>
|
<p><a href="{{ 10000069|zkillboard_region_url}}">region from ID</a></p>
|
||||||
<p><a href="{{ 30002813|zkillboard_solar_system_url}}">solar sytem from ID</a></p>
|
<p><a href="{{ 30002813|zkillboard_solar_system_url}}">solar sytem from ID</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>image URLs</h2>
|
<h2>image URLs</h2>
|
||||||
|
|
||||||
<div class="rows">
|
<div class="rows">
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<p>character from ID: <img src="{{ my_character.character_id|character_portrait_url:128}}"></p>
|
<p>character from ID: <img src="{{ my_character.character_id|character_portrait_url:128}}"></p>
|
||||||
<p>character from character object: <img src="{{ my_character|character_portrait_url:128}}"></p>
|
<p>character from character object: <img src="{{ my_character|character_portrait_url:128}}"></p>
|
||||||
@ -67,18 +67,18 @@ Needs to be called with a context containing three objects:
|
|||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<p>corporation from ID: <img src="{{ my_character.corporation_id|corporation_logo_url:128}}"></p>
|
<p>corporation from ID: <img src="{{ my_character.corporation_id|corporation_logo_url:128}}"></p>
|
||||||
<p>corporation from character object: <img src="{{ my_character|corporation_logo_url:128}}"></p>
|
<p>corporation from character object: <img src="{{ my_character|corporation_logo_url:128}}"></p>
|
||||||
<p>corporation from corporation object: <img src="{{ my_corporation|corporation_logo_url:128}}"></p>
|
<p>corporation from corporation object: <img src="{{ my_corporation|corporation_logo_url:128}}"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<p>alliance from ID: <img src="{{ my_character.alliance_id|alliance_logo_url:128}}"></p>
|
<p>alliance from ID: <img src="{{ my_character.alliance_id|alliance_logo_url:128}}"></p>
|
||||||
<p>alliance from character object: <img src="{{ my_character|alliance_logo_url:128}}"></p>
|
<p>alliance from character object: <img src="{{ my_character|alliance_logo_url:128}}"></p>
|
||||||
<p>alliance from alliance object: <img src="{{ my_alliance|alliance_logo_url:128}}"></p>
|
<p>alliance from alliance object: <img src="{{ my_alliance|alliance_logo_url:128}}"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def set_logger(logger_name: str, name: str) -> object:
|
def set_logger(logger_name: str, name: str) -> object:
|
||||||
"""set logger for current test module
|
"""set logger for current test module
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
- logger: current logger object
|
- logger: current logger object
|
||||||
- name: name of current module, e.g. __file__
|
- name: name of current module, e.g. __file__
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- amended logger
|
- amended logger
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# reconfigure logger so we get logging from tested module
|
# reconfigure logger so we get logging from tested module
|
||||||
f_format = logging.Formatter(
|
f_format = logging.Formatter(
|
||||||
'%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s'
|
'%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s'
|
||||||
|
|||||||
@ -27,9 +27,9 @@ class EveCharacterManagerTestCase(TestCase):
|
|||||||
@property
|
@property
|
||||||
def corp(self):
|
def corp(self):
|
||||||
return Corporation(
|
return Corporation(
|
||||||
id=2345,
|
id=2345,
|
||||||
name='Test Corp',
|
name='Test Corp',
|
||||||
alliance_id=3456,
|
alliance_id=3456,
|
||||||
ticker='0BUGS' #lies, blatant lies!
|
ticker='0BUGS' #lies, blatant lies!
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,9 +37,9 @@ class EveCharacterManagerTestCase(TestCase):
|
|||||||
def test_create_character(self, provider):
|
def test_create_character(self, provider):
|
||||||
# Also covers create_character_obj
|
# Also covers create_character_obj
|
||||||
expected = self.TestCharacter(
|
expected = self.TestCharacter(
|
||||||
id=1234,
|
id=1234,
|
||||||
name='Test Character',
|
name='Test Character',
|
||||||
corp_id=2345,
|
corp_id=2345,
|
||||||
alliance_id=3456
|
alliance_id=3456
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,9 +69,9 @@ class EveCharacterManagerTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
expected = self.TestCharacter(
|
expected = self.TestCharacter(
|
||||||
id=1234,
|
id=1234,
|
||||||
name='Test Character',
|
name='Test Character',
|
||||||
corp_id=2345,
|
corp_id=2345,
|
||||||
alliance_id=3456
|
alliance_id=3456
|
||||||
)
|
)
|
||||||
provider.get_character.return_value = expected
|
provider.get_character.return_value = expected
|
||||||
@ -104,7 +104,7 @@ class EveCharacterManagerTestCase(TestCase):
|
|||||||
self.assertEqual(result.character_id, 1234)
|
self.assertEqual(result.character_id, 1234)
|
||||||
self.assertEqual(result.character_name, 'character.name')
|
self.assertEqual(result.character_name, 'character.name')
|
||||||
|
|
||||||
# try to get non existing character
|
# try to get non existing character
|
||||||
self.assertIsNone(EveCharacter.objects.get_character_by_id(9999))
|
self.assertIsNone(EveCharacter.objects.get_character_by_id(9999))
|
||||||
|
|
||||||
|
|
||||||
@ -130,10 +130,10 @@ class EveAllianceManagerTestCase(TestCase):
|
|||||||
def test_create_alliance(self, provider, populate_alliance):
|
def test_create_alliance(self, provider, populate_alliance):
|
||||||
# Also covers create_alliance_obj
|
# Also covers create_alliance_obj
|
||||||
expected = self.TestAlliance(
|
expected = self.TestAlliance(
|
||||||
id=3456,
|
id=3456,
|
||||||
name='Test Alliance',
|
name='Test Alliance',
|
||||||
ticker='TEST',
|
ticker='TEST',
|
||||||
corp_ids=[2345],
|
corp_ids=[2345],
|
||||||
executor_corp_id=2345
|
executor_corp_id=2345
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -157,10 +157,10 @@ class EveAllianceManagerTestCase(TestCase):
|
|||||||
executor_corp_id=2345,
|
executor_corp_id=2345,
|
||||||
)
|
)
|
||||||
expected = self.TestAlliance(
|
expected = self.TestAlliance(
|
||||||
id=3456,
|
id=3456,
|
||||||
name='Test Alliance',
|
name='Test Alliance',
|
||||||
ticker='TEST',
|
ticker='TEST',
|
||||||
corp_ids=[2345],
|
corp_ids=[2345],
|
||||||
executor_corp_id=2345
|
executor_corp_id=2345
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -189,19 +189,19 @@ class EveCorporationManagerTestCase(TestCase):
|
|||||||
@property
|
@property
|
||||||
def alliance(self):
|
def alliance(self):
|
||||||
return EveAllianceManagerTestCase.TestAlliance(
|
return EveAllianceManagerTestCase.TestAlliance(
|
||||||
id=3456,
|
id=3456,
|
||||||
name='Test Alliance',
|
name='Test Alliance',
|
||||||
ticker='TEST',
|
ticker='TEST',
|
||||||
corp_ids=[2345],
|
corp_ids=[2345],
|
||||||
executor_corp_id=2345
|
executor_corp_id=2345
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ceo(self):
|
def ceo(self):
|
||||||
return EveCharacterManagerTestCase.TestCharacter(
|
return EveCharacterManagerTestCase.TestCharacter(
|
||||||
id=1234,
|
id=1234,
|
||||||
name='Test Character',
|
name='Test Character',
|
||||||
corp_id=2345,
|
corp_id=2345,
|
||||||
alliance_id=3456
|
alliance_id=3456
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -216,11 +216,11 @@ class EveCorporationManagerTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
expected = self.TestCorporation(
|
expected = self.TestCorporation(
|
||||||
id=2345,
|
id=2345,
|
||||||
name='Test Corp',
|
name='Test Corp',
|
||||||
ticker='0BUGS',
|
ticker='0BUGS',
|
||||||
ceo_id=1234,
|
ceo_id=1234,
|
||||||
members=1,
|
members=1,
|
||||||
alliance_id=3456
|
alliance_id=3456
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -237,13 +237,13 @@ class EveCorporationManagerTestCase(TestCase):
|
|||||||
@mock.patch('allianceauth.eveonline.managers.providers.provider')
|
@mock.patch('allianceauth.eveonline.managers.providers.provider')
|
||||||
def test_create_corporation_no_alliance(self, provider):
|
def test_create_corporation_no_alliance(self, provider):
|
||||||
# variant to test no alliance case
|
# variant to test no alliance case
|
||||||
# Also covers create_corp_obj
|
# Also covers create_corp_obj
|
||||||
expected = self.TestCorporation(
|
expected = self.TestCorporation(
|
||||||
id=2345,
|
id=2345,
|
||||||
name='Test Corp',
|
name='Test Corp',
|
||||||
ticker='0BUGS',
|
ticker='0BUGS',
|
||||||
ceo_id=1234,
|
ceo_id=1234,
|
||||||
members=1,
|
members=1,
|
||||||
alliance_id=3456
|
alliance_id=3456
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -276,11 +276,11 @@ class EveCorporationManagerTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
expected = self.TestCorporation(
|
expected = self.TestCorporation(
|
||||||
id=2345,
|
id=2345,
|
||||||
name='Test Corp',
|
name='Test Corp',
|
||||||
ticker='0BUGS',
|
ticker='0BUGS',
|
||||||
ceo_id=1234,
|
ceo_id=1234,
|
||||||
members=1,
|
members=1,
|
||||||
alliance_id=3456
|
alliance_id=3456
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -133,9 +133,9 @@ class EveCharacterTestCase(TestCase):
|
|||||||
name='Dummy Corp 2',
|
name='Dummy Corp 2',
|
||||||
ticker='DC2',
|
ticker='DC2',
|
||||||
ceo_id=1001,
|
ceo_id=1001,
|
||||||
members=34,
|
members=34,
|
||||||
)
|
)
|
||||||
|
|
||||||
my_character = EveCharacter.objects.create(
|
my_character = EveCharacter.objects.create(
|
||||||
character_id=1001,
|
character_id=1001,
|
||||||
character_name='Bruce Wayne',
|
character_name='Bruce Wayne',
|
||||||
@ -144,7 +144,7 @@ class EveCharacterTestCase(TestCase):
|
|||||||
corporation_ticker='DC1',
|
corporation_ticker='DC1',
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
alliance_name='Dummy Alliance 1',
|
alliance_name='Dummy Alliance 1',
|
||||||
)
|
)
|
||||||
my_updated_character = Character(
|
my_updated_character = Character(
|
||||||
name='Bruce X. Wayne',
|
name='Bruce X. Wayne',
|
||||||
corp_id=2002
|
corp_id=2002
|
||||||
@ -169,8 +169,8 @@ class EveCharacterTestCase(TestCase):
|
|||||||
character_id=42,
|
character_id=42,
|
||||||
character_name='character.name',
|
character_name='character.name',
|
||||||
corporation_id=123,
|
corporation_id=123,
|
||||||
corporation_name='corporation.name',
|
corporation_name='corporation.name',
|
||||||
corporation_ticker='ABC',
|
corporation_ticker='ABC',
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.portrait_url(),
|
x.portrait_url(),
|
||||||
@ -179,7 +179,7 @@ class EveCharacterTestCase(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.portrait_url(64),
|
x.portrait_url(64),
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=64)
|
eveimageserver._eve_entity_image_url('character', 42, size=64)
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.portrait_url_32,
|
x.portrait_url_32,
|
||||||
eveimageserver._eve_entity_image_url('character', 42, size=32)
|
eveimageserver._eve_entity_image_url('character', 42, size=32)
|
||||||
@ -202,8 +202,8 @@ class EveCharacterTestCase(TestCase):
|
|||||||
character_id=42,
|
character_id=42,
|
||||||
character_name='character.name',
|
character_name='character.name',
|
||||||
corporation_id=123,
|
corporation_id=123,
|
||||||
corporation_name='corporation.name',
|
corporation_name='corporation.name',
|
||||||
corporation_ticker='ABC',
|
corporation_ticker='ABC',
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.corporation_logo_url(),
|
x.corporation_logo_url(),
|
||||||
@ -235,9 +235,9 @@ class EveCharacterTestCase(TestCase):
|
|||||||
character_id=42,
|
character_id=42,
|
||||||
character_name='character.name',
|
character_name='character.name',
|
||||||
corporation_id=123,
|
corporation_id=123,
|
||||||
corporation_name='corporation.name',
|
corporation_name='corporation.name',
|
||||||
corporation_ticker='ABC',
|
corporation_ticker='ABC',
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.alliance_logo_url(),
|
x.alliance_logo_url(),
|
||||||
''
|
''
|
||||||
@ -286,7 +286,7 @@ class EveCharacterTestCase(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class EveAllianceTestCase(TestCase):
|
class EveAllianceTestCase(TestCase):
|
||||||
|
|
||||||
def test_str(self):
|
def test_str(self):
|
||||||
my_alliance = EveAllianceInfo(
|
my_alliance = EveAllianceInfo(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
@ -295,12 +295,12 @@ class EveAllianceTestCase(TestCase):
|
|||||||
executor_corp_id=2001
|
executor_corp_id=2001
|
||||||
)
|
)
|
||||||
self.assertEqual(str(my_alliance), 'Dummy Alliance 1')
|
self.assertEqual(str(my_alliance), 'Dummy Alliance 1')
|
||||||
|
|
||||||
@patch(
|
@patch(
|
||||||
'allianceauth.eveonline.models.EveCorporationInfo.objects.create_corporation'
|
'allianceauth.eveonline.models.EveCorporationInfo.objects.create_corporation'
|
||||||
)
|
)
|
||||||
def test_populate_alliance(self, mock_create_corporation):
|
def test_populate_alliance(self, mock_create_corporation):
|
||||||
|
|
||||||
def create_corp(corp_id):
|
def create_corp(corp_id):
|
||||||
if corp_id == 2002:
|
if corp_id == 2002:
|
||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
@ -311,23 +311,23 @@ class EveAllianceTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
mock_EveAllianceProviderManager = Mock()
|
mock_EveAllianceProviderManager = Mock()
|
||||||
mock_EveAllianceProviderManager.get_alliance.return_value = \
|
mock_EveAllianceProviderManager.get_alliance.return_value = \
|
||||||
Alliance(
|
Alliance(
|
||||||
id=3001,
|
id=3001,
|
||||||
name='Dummy Alliance 1',
|
name='Dummy Alliance 1',
|
||||||
corp_ids=[2001, 2002]
|
corp_ids=[2001, 2002]
|
||||||
)
|
)
|
||||||
mock_create_corporation.side_effect = create_corp
|
mock_create_corporation.side_effect = create_corp
|
||||||
|
|
||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2001,
|
corporation_id=2001,
|
||||||
corporation_name='Dummy Corporation 1',
|
corporation_name='Dummy Corporation 1',
|
||||||
corporation_ticker='DC1',
|
corporation_ticker='DC1',
|
||||||
member_count=42,
|
member_count=42,
|
||||||
)
|
)
|
||||||
|
|
||||||
my_alliance = EveAllianceInfo(
|
my_alliance = EveAllianceInfo(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
alliance_name='Dummy Alliance 1',
|
alliance_name='Dummy Alliance 1',
|
||||||
@ -336,13 +336,13 @@ class EveAllianceTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
my_alliance.provider = mock_EveAllianceProviderManager
|
my_alliance.provider = mock_EveAllianceProviderManager
|
||||||
my_alliance.save()
|
my_alliance.save()
|
||||||
my_alliance.populate_alliance()
|
my_alliance.populate_alliance()
|
||||||
|
|
||||||
for corporation in EveCorporationInfo.objects\
|
for corporation in EveCorporationInfo.objects\
|
||||||
.filter(corporation_id__in=[2001, 2002]
|
.filter(corporation_id__in=[2001, 2002]
|
||||||
):
|
):
|
||||||
self.assertEqual(corporation.alliance, my_alliance)
|
self.assertEqual(corporation.alliance, my_alliance)
|
||||||
|
|
||||||
def test_update_alliance_with_object(self):
|
def test_update_alliance_with_object(self):
|
||||||
my_alliance = EveAllianceInfo.objects.create(
|
my_alliance = EveAllianceInfo.objects.create(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
@ -351,9 +351,9 @@ class EveAllianceTestCase(TestCase):
|
|||||||
executor_corp_id=2001
|
executor_corp_id=2001
|
||||||
)
|
)
|
||||||
updated_alliance = Alliance(
|
updated_alliance = Alliance(
|
||||||
id=3002,
|
id=3002,
|
||||||
name='Dummy Alliance 2',
|
name='Dummy Alliance 2',
|
||||||
corp_ids=[2004],
|
corp_ids=[2004],
|
||||||
executor_corp_id=2004
|
executor_corp_id=2004
|
||||||
)
|
)
|
||||||
my_alliance.update_alliance(updated_alliance)
|
my_alliance.update_alliance(updated_alliance)
|
||||||
@ -367,7 +367,7 @@ class EveAllianceTestCase(TestCase):
|
|||||||
mock_EveAllianceProviderManager = Mock()
|
mock_EveAllianceProviderManager = Mock()
|
||||||
mock_EveAllianceProviderManager.get_alliance.return_value = \
|
mock_EveAllianceProviderManager.get_alliance.return_value = \
|
||||||
Alliance(
|
Alliance(
|
||||||
id=3002,
|
id=3002,
|
||||||
name='Dummy Alliance 2',
|
name='Dummy Alliance 2',
|
||||||
corp_ids=[2004],
|
corp_ids=[2004],
|
||||||
executor_corp_id=2004
|
executor_corp_id=2004
|
||||||
@ -381,15 +381,15 @@ class EveAllianceTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
my_alliance.provider = mock_EveAllianceProviderManager
|
my_alliance.provider = mock_EveAllianceProviderManager
|
||||||
my_alliance.save()
|
my_alliance.save()
|
||||||
Alliance(
|
Alliance(
|
||||||
name='Dummy Alliance 2',
|
name='Dummy Alliance 2',
|
||||||
corp_ids=[2004],
|
corp_ids=[2004],
|
||||||
executor_corp_id=2004
|
executor_corp_id=2004
|
||||||
)
|
)
|
||||||
my_alliance.update_alliance()
|
my_alliance.update_alliance()
|
||||||
my_alliance.refresh_from_db()
|
my_alliance.refresh_from_db()
|
||||||
self.assertEqual(int(my_alliance.executor_corp_id), 2004)
|
self.assertEqual(int(my_alliance.executor_corp_id), 2004)
|
||||||
|
|
||||||
# potential bug
|
# potential bug
|
||||||
# update_alliance() is only updateting executor_corp_id nothing else ???
|
# update_alliance() is only updateting executor_corp_id nothing else ???
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ class EveAllianceTestCase(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.logo_url(64),
|
x.logo_url(64),
|
||||||
'https://images.evetech.net/alliances/42/logo?size=64'
|
'https://images.evetech.net/alliances/42/logo?size=64'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.logo_url_32,
|
x.logo_url_32,
|
||||||
'https://images.evetech.net/alliances/42/logo?size=32'
|
'https://images.evetech.net/alliances/42/logo?size=32'
|
||||||
@ -434,10 +434,10 @@ class EveAllianceTestCase(TestCase):
|
|||||||
x.logo_url_256,
|
x.logo_url_256,
|
||||||
'https://images.evetech.net/alliances/42/logo?size=256'
|
'https://images.evetech.net/alliances/42/logo?size=256'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EveCorporationTestCase(TestCase):
|
class EveCorporationTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
my_alliance = EveAllianceInfo.objects.create(
|
my_alliance = EveAllianceInfo.objects.create(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
@ -451,9 +451,9 @@ class EveCorporationTestCase(TestCase):
|
|||||||
corporation_ticker='DC1',
|
corporation_ticker='DC1',
|
||||||
member_count=42,
|
member_count=42,
|
||||||
alliance=my_alliance
|
alliance=my_alliance
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_str(self):
|
def test_str(self):
|
||||||
self.assertEqual(str(self.my_corp), 'Dummy Corporation 1')
|
self.assertEqual(str(self.my_corp), 'Dummy Corporation 1')
|
||||||
|
|
||||||
def test_update_corporation_from_object_w_alliance(self):
|
def test_update_corporation_from_object_w_alliance(self):
|
||||||
@ -465,15 +465,15 @@ class EveCorporationTestCase(TestCase):
|
|||||||
|
|
||||||
# potential bug
|
# potential bug
|
||||||
# update_corporation updates member_count only
|
# update_corporation updates member_count only
|
||||||
|
|
||||||
def test_update_corporation_no_object_w_alliance(self):
|
def test_update_corporation_no_object_w_alliance(self):
|
||||||
mock_provider = Mock()
|
mock_provider = Mock()
|
||||||
mock_provider.get_corporation.return_value = Corporation(members=87)
|
mock_provider.get_corporation.return_value = Corporation(members=87)
|
||||||
self.my_corp.provider = mock_provider
|
self.my_corp.provider = mock_provider
|
||||||
|
|
||||||
self.my_corp.update_corporation()
|
self.my_corp.update_corporation()
|
||||||
self.assertEqual(self.my_corp.member_count, 87)
|
self.assertEqual(self.my_corp.member_count, 87)
|
||||||
|
|
||||||
def test_update_corporation_from_object_wo_alliance(self):
|
def test_update_corporation_from_object_wo_alliance(self):
|
||||||
my_corp2 = EveCorporationInfo(
|
my_corp2 = EveCorporationInfo(
|
||||||
corporation_id=2011,
|
corporation_id=2011,
|
||||||
@ -498,7 +498,7 @@ class EveCorporationTestCase(TestCase):
|
|||||||
eveimageserver._eve_entity_image_url('corporation', 42, 256)
|
eveimageserver._eve_entity_image_url('corporation', 42, 256)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_logo_url(self):
|
def test_logo_url(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.my_corp.logo_url(),
|
self.my_corp.logo_url(),
|
||||||
'https://images.evetech.net/corporations/2001/logo?size=32'
|
'https://images.evetech.net/corporations/2001/logo?size=32'
|
||||||
|
|||||||
@ -8,13 +8,13 @@ from django.test import TestCase
|
|||||||
|
|
||||||
from . import set_logger
|
from . import set_logger
|
||||||
from ..providers import (
|
from ..providers import (
|
||||||
ObjectNotFound,
|
ObjectNotFound,
|
||||||
Entity,
|
Entity,
|
||||||
Character,
|
Character,
|
||||||
Corporation,
|
Corporation,
|
||||||
Alliance,
|
Alliance,
|
||||||
ItemType,
|
ItemType,
|
||||||
EveProvider,
|
EveProvider,
|
||||||
EveSwaggerProvider
|
EveSwaggerProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -92,12 +92,12 @@ class TestCorporation(TestCase):
|
|||||||
executor_corp_id=2001
|
executor_corp_id=2001
|
||||||
)
|
)
|
||||||
mock_provider_get_alliance.return_value = my_alliance
|
mock_provider_get_alliance.return_value = my_alliance
|
||||||
|
|
||||||
x = Corporation(alliance_id=3001)
|
x = Corporation(alliance_id=3001)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.alliance,
|
x.alliance,
|
||||||
my_alliance
|
my_alliance
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.alliance,
|
x.alliance,
|
||||||
my_alliance
|
my_alliance
|
||||||
@ -106,25 +106,25 @@ class TestCorporation(TestCase):
|
|||||||
self.assertEqual(mock_provider_get_alliance.call_count, 1)
|
self.assertEqual(mock_provider_get_alliance.call_count, 1)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.EveSwaggerProvider.get_alliance')
|
@patch(MODULE_PATH + '.EveSwaggerProvider.get_alliance')
|
||||||
def test_alliance_not_defined(self, mock_provider_get_alliance):
|
def test_alliance_not_defined(self, mock_provider_get_alliance):
|
||||||
mock_provider_get_alliance.return_value = None
|
mock_provider_get_alliance.return_value = None
|
||||||
|
|
||||||
x = Corporation()
|
x = Corporation()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
x.alliance,
|
x.alliance,
|
||||||
Entity(None, None)
|
Entity(None, None)
|
||||||
)
|
)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.EveSwaggerProvider.get_character')
|
@patch(MODULE_PATH + '.EveSwaggerProvider.get_character')
|
||||||
def test_ceo(self, mock_provider_get_character):
|
def test_ceo(self, mock_provider_get_character):
|
||||||
my_ceo = Character(
|
my_ceo = Character(
|
||||||
id=1001,
|
id=1001,
|
||||||
name='Bruce Wayne',
|
name='Bruce Wayne',
|
||||||
corp_id=2001,
|
corp_id=2001,
|
||||||
alliance_id=3001
|
alliance_id=3001
|
||||||
)
|
)
|
||||||
mock_provider_get_character.return_value = my_ceo
|
mock_provider_get_character.return_value = my_ceo
|
||||||
|
|
||||||
# fetch from provider if not defined
|
# fetch from provider if not defined
|
||||||
x = Corporation()
|
x = Corporation()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -142,7 +142,7 @@ class TestCorporation(TestCase):
|
|||||||
|
|
||||||
# bug in ceo(): will try to fetch character even if ceo_id is None
|
# bug in ceo(): will try to fetch character even if ceo_id is None
|
||||||
|
|
||||||
|
|
||||||
class TestAlliance(TestCase):
|
class TestAlliance(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -155,48 +155,48 @@ class TestAlliance(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_corp(corp_id):
|
def _get_corp(corp_id):
|
||||||
corps = {
|
corps = {
|
||||||
2001: Corporation(
|
2001: Corporation(
|
||||||
id=2001,
|
id=2001,
|
||||||
name='Dummy Corp 1',
|
name='Dummy Corp 1',
|
||||||
alliance_id=3001
|
alliance_id=3001
|
||||||
),
|
),
|
||||||
2002: Corporation(
|
2002: Corporation(
|
||||||
id=2002,
|
id=2002,
|
||||||
name='Dummy Corp 2',
|
name='Dummy Corp 2',
|
||||||
alliance_id=3001
|
alliance_id=3001
|
||||||
),
|
),
|
||||||
2003: Corporation(
|
2003: Corporation(
|
||||||
id=2003,
|
id=2003,
|
||||||
name='Dummy Corp 3',
|
name='Dummy Corp 3',
|
||||||
alliance_id=3001
|
alliance_id=3001
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
if corp_id:
|
if corp_id:
|
||||||
return corps[int(corp_id)]
|
return corps[int(corp_id)]
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.EveSwaggerProvider.get_corp')
|
@patch(MODULE_PATH + '.EveSwaggerProvider.get_corp')
|
||||||
def test_corp(self, mock_provider_get_corp):
|
def test_corp(self, mock_provider_get_corp):
|
||||||
mock_provider_get_corp.side_effect = TestAlliance._get_corp
|
mock_provider_get_corp.side_effect = TestAlliance._get_corp
|
||||||
|
|
||||||
# should fetch corp if not in the object
|
# should fetch corp if not in the object
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.my_alliance.corp(2001),
|
self.my_alliance.corp(2001),
|
||||||
TestAlliance._get_corp(2001)
|
TestAlliance._get_corp(2001)
|
||||||
)
|
)
|
||||||
# should fetch corp if not in the object
|
# should fetch corp if not in the object
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.my_alliance.corp(2002),
|
self.my_alliance.corp(2002),
|
||||||
TestAlliance._get_corp(2002)
|
TestAlliance._get_corp(2002)
|
||||||
)
|
)
|
||||||
# should return from the object if its there
|
# should return from the object if its there
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.my_alliance.corp(2001),
|
self.my_alliance.corp(2001),
|
||||||
TestAlliance._get_corp(2001)
|
TestAlliance._get_corp(2001)
|
||||||
)
|
)
|
||||||
# should return from the object if its there
|
# should return from the object if its there
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.my_alliance.corp(2002),
|
self.my_alliance.corp(2002),
|
||||||
TestAlliance._get_corp(2002)
|
TestAlliance._get_corp(2002)
|
||||||
@ -220,7 +220,7 @@ class TestAlliance(TestCase):
|
|||||||
@patch(MODULE_PATH + '.EveSwaggerProvider.get_corp')
|
@patch(MODULE_PATH + '.EveSwaggerProvider.get_corp')
|
||||||
def test_executor_corp(self, mock_provider_get_corp):
|
def test_executor_corp(self, mock_provider_get_corp):
|
||||||
mock_provider_get_corp.side_effect = TestAlliance._get_corp
|
mock_provider_get_corp.side_effect = TestAlliance._get_corp
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.my_alliance.executor_corp,
|
self.my_alliance.executor_corp,
|
||||||
TestAlliance._get_corp(2001),
|
TestAlliance._get_corp(2001),
|
||||||
@ -248,7 +248,7 @@ class TestCharacter(TestCase):
|
|||||||
my_corp = Corporation(
|
my_corp = Corporation(
|
||||||
id=2001,
|
id=2001,
|
||||||
name='Dummy Corp 1'
|
name='Dummy Corp 1'
|
||||||
)
|
)
|
||||||
mock_provider_get_corp.return_value = my_corp
|
mock_provider_get_corp.return_value = my_corp
|
||||||
|
|
||||||
self.assertEqual(self.my_character.corp, my_corp)
|
self.assertEqual(self.my_character.corp, my_corp)
|
||||||
@ -256,11 +256,11 @@ class TestCharacter(TestCase):
|
|||||||
|
|
||||||
# should call the provider one time only
|
# should call the provider one time only
|
||||||
self.assertEqual(mock_provider_get_corp.call_count, 1)
|
self.assertEqual(mock_provider_get_corp.call_count, 1)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.EveSwaggerProvider.get_alliance')
|
@patch(MODULE_PATH + '.EveSwaggerProvider.get_alliance')
|
||||||
@patch(MODULE_PATH + '.EveSwaggerProvider.get_corp')
|
@patch(MODULE_PATH + '.EveSwaggerProvider.get_corp')
|
||||||
def test_alliance_has_one(
|
def test_alliance_has_one(
|
||||||
self,
|
self,
|
||||||
mock_provider_get_corp,
|
mock_provider_get_corp,
|
||||||
mock_provider_get_alliance,
|
mock_provider_get_alliance,
|
||||||
):
|
):
|
||||||
@ -268,14 +268,14 @@ class TestCharacter(TestCase):
|
|||||||
id=2001,
|
id=2001,
|
||||||
name='Dummy Corp 1',
|
name='Dummy Corp 1',
|
||||||
alliance_id=3001
|
alliance_id=3001
|
||||||
)
|
)
|
||||||
mock_provider_get_corp.return_value = my_corp
|
mock_provider_get_corp.return_value = my_corp
|
||||||
my_alliance = Alliance(
|
my_alliance = Alliance(
|
||||||
id=3001,
|
id=3001,
|
||||||
name='Dummy Alliance 1',
|
name='Dummy Alliance 1',
|
||||||
executor_corp_id=2001,
|
executor_corp_id=2001,
|
||||||
corp_ids=[2001, 2002]
|
corp_ids=[2001, 2002]
|
||||||
)
|
)
|
||||||
mock_provider_get_alliance.return_value = my_alliance
|
mock_provider_get_alliance.return_value = my_alliance
|
||||||
|
|
||||||
self.assertEqual(self.my_character.alliance, my_alliance)
|
self.assertEqual(self.my_character.alliance, my_alliance)
|
||||||
@ -301,7 +301,7 @@ class TestEveProvider(TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.my_provider = EveProvider()
|
self.my_provider = EveProvider()
|
||||||
|
|
||||||
def test_get_alliance(self):
|
def test_get_alliance(self):
|
||||||
with self.assertRaises(NotImplementedError):
|
with self.assertRaises(NotImplementedError):
|
||||||
self.my_provider.get_alliance(3001)
|
self.my_provider.get_alliance(3001)
|
||||||
@ -315,7 +315,7 @@ class TestEveProvider(TestCase):
|
|||||||
self.my_provider.get_character(1001)
|
self.my_provider.get_character(1001)
|
||||||
|
|
||||||
# bug: should be calling NotImplementedError() not NotImplemented
|
# bug: should be calling NotImplementedError() not NotImplemented
|
||||||
"""
|
"""
|
||||||
def test_get_itemtype(self):
|
def test_get_itemtype(self):
|
||||||
with self.assertRaises(NotImplementedError):
|
with self.assertRaises(NotImplementedError):
|
||||||
self.my_provider.get_itemtype(4001)
|
self.my_provider.get_itemtype(4001)
|
||||||
@ -323,7 +323,7 @@ class TestEveProvider(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestEveSwaggerProvider(TestCase):
|
class TestEveSwaggerProvider(TestCase):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def esi_get_alliances_alliance_id(alliance_id):
|
def esi_get_alliances_alliance_id(alliance_id):
|
||||||
alliances = {
|
alliances = {
|
||||||
@ -404,11 +404,11 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def esi_post_characters_affiliation(characters):
|
def esi_post_characters_affiliation(characters):
|
||||||
character_data = {
|
character_data = {
|
||||||
1001: {
|
1001: {
|
||||||
'corporation_id': 2001,
|
'corporation_id': 2001,
|
||||||
'alliance_id': 3001
|
'alliance_id': 3001
|
||||||
},
|
},
|
||||||
1002: {
|
1002: {
|
||||||
'corporation_id': 2101
|
'corporation_id': 2101
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,7 +424,7 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
return mock_result
|
return mock_result
|
||||||
else:
|
else:
|
||||||
raise TypeError()
|
raise TypeError()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def esi_get_universe_types_type_id(type_id):
|
def esi_get_universe_types_type_id(type_id):
|
||||||
types = {
|
types = {
|
||||||
@ -443,7 +443,7 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
raise HTTPNotFound(Mock())
|
raise HTTPNotFound(Mock())
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.esi_client_factory')
|
@patch(MODULE_PATH + '.esi_client_factory')
|
||||||
def test_str(self, mock_esi_client_factory):
|
def test_str(self, mock_esi_client_factory):
|
||||||
my_provider = EveSwaggerProvider()
|
my_provider = EveSwaggerProvider()
|
||||||
self.assertEqual(str(my_provider), 'esi')
|
self.assertEqual(str(my_provider), 'esi')
|
||||||
|
|
||||||
@ -457,7 +457,7 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
= TestEveSwaggerProvider.esi_get_alliances_alliance_id_corporations
|
= TestEveSwaggerProvider.esi_get_alliances_alliance_id_corporations
|
||||||
|
|
||||||
my_provider = EveSwaggerProvider()
|
my_provider = EveSwaggerProvider()
|
||||||
|
|
||||||
# fully defined alliance
|
# fully defined alliance
|
||||||
my_alliance = my_provider.get_alliance(3001)
|
my_alliance = my_provider.get_alliance(3001)
|
||||||
self.assertEqual(my_alliance.id, 3001)
|
self.assertEqual(my_alliance.id, 3001)
|
||||||
@ -494,13 +494,13 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
|
|
||||||
# corporation wo/ alliance
|
# corporation wo/ alliance
|
||||||
my_corp = my_provider.get_corp(2002)
|
my_corp = my_provider.get_corp(2002)
|
||||||
self.assertEqual(my_corp.id, 2002)
|
self.assertEqual(my_corp.id, 2002)
|
||||||
self.assertEqual(my_corp.alliance_id, None)
|
self.assertEqual(my_corp.alliance_id, None)
|
||||||
|
|
||||||
# corporation not found
|
# corporation not found
|
||||||
with self.assertRaises(ObjectNotFound):
|
with self.assertRaises(ObjectNotFound):
|
||||||
my_provider.get_corp(2999)
|
my_provider.get_corp(2999)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.esi_client_factory')
|
@patch(MODULE_PATH + '.esi_client_factory')
|
||||||
def test_get_character(self, mock_esi_client_factory):
|
def test_get_character(self, mock_esi_client_factory):
|
||||||
mock_esi_client_factory.return_value\
|
mock_esi_client_factory.return_value\
|
||||||
@ -540,7 +540,7 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
my_type = my_provider.get_itemtype(4001)
|
my_type = my_provider.get_itemtype(4001)
|
||||||
self.assertEqual(my_type.id, 4001)
|
self.assertEqual(my_type.id, 4001)
|
||||||
self.assertEqual(my_type.name, 'Dummy Type 1')
|
self.assertEqual(my_type.name, 'Dummy Type 1')
|
||||||
|
|
||||||
# type not found
|
# type not found
|
||||||
with self.assertRaises(ObjectNotFound):
|
with self.assertRaises(ObjectNotFound):
|
||||||
my_provider.get_itemtype(4999)
|
my_provider.get_itemtype(4999)
|
||||||
@ -551,7 +551,7 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
my_provider = EveSwaggerProvider()
|
my_provider = EveSwaggerProvider()
|
||||||
self.assertTrue(mock_esi_client_factory.called)
|
self.assertTrue(mock_esi_client_factory.called)
|
||||||
self.assertIsNotNone(my_provider._client)
|
self.assertIsNotNone(my_provider._client)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.SWAGGER_SPEC_PATH', SWAGGER_OLD_SPEC_PATH)
|
@patch(MODULE_PATH + '.SWAGGER_SPEC_PATH', SWAGGER_OLD_SPEC_PATH)
|
||||||
@patch(MODULE_PATH + '.settings.DEBUG', False)
|
@patch(MODULE_PATH + '.settings.DEBUG', False)
|
||||||
@patch('socket.socket')
|
@patch('socket.socket')
|
||||||
@ -559,8 +559,8 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
self, mock_socket
|
self, mock_socket
|
||||||
):
|
):
|
||||||
mock_socket.side_effect = Exception('Network blocked for testing')
|
mock_socket.side_effect = Exception('Network blocked for testing')
|
||||||
my_provider = EveSwaggerProvider()
|
my_provider = EveSwaggerProvider()
|
||||||
self.assertIsNone(my_provider._client)
|
self.assertIsNone(my_provider._client)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.settings.DEBUG', True)
|
@patch(MODULE_PATH + '.settings.DEBUG', True)
|
||||||
@patch(MODULE_PATH + '.esi_client_factory')
|
@patch(MODULE_PATH + '.esi_client_factory')
|
||||||
|
|||||||
@ -4,9 +4,9 @@ from django.test import TestCase
|
|||||||
|
|
||||||
from ..models import EveCharacter, EveCorporationInfo, EveAllianceInfo
|
from ..models import EveCharacter, EveCorporationInfo, EveAllianceInfo
|
||||||
from ..tasks import (
|
from ..tasks import (
|
||||||
update_alliance,
|
update_alliance,
|
||||||
update_corp,
|
update_corp,
|
||||||
update_character,
|
update_character,
|
||||||
run_model_update
|
run_model_update
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ class TestTasks(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mock_EveCorporationInfo.objects.update_corporation.call_args[0][0], 42
|
mock_EveCorporationInfo.objects.update_corporation.call_args[0][0], 42
|
||||||
)
|
)
|
||||||
|
|
||||||
@patch('allianceauth.eveonline.tasks.EveAllianceInfo')
|
@patch('allianceauth.eveonline.tasks.EveAllianceInfo')
|
||||||
def test_update_alliance(self, mock_EveAllianceInfo):
|
def test_update_alliance(self, mock_EveAllianceInfo):
|
||||||
update_alliance(42)
|
update_alliance(42)
|
||||||
@ -58,7 +58,7 @@ class TestRunModelUpdate(TestCase):
|
|||||||
EveCorporationInfo.objects.all().delete()
|
EveCorporationInfo.objects.all().delete()
|
||||||
EveAllianceInfo.objects.all().delete()
|
EveAllianceInfo.objects.all().delete()
|
||||||
EveCharacter.objects.all().delete()
|
EveCharacter.objects.all().delete()
|
||||||
|
|
||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2345,
|
corporation_id=2345,
|
||||||
corporation_name='corp.name',
|
corporation_name='corp.name',
|
||||||
@ -71,13 +71,13 @@ class TestRunModelUpdate(TestCase):
|
|||||||
alliance_name='alliance.name',
|
alliance_name='alliance.name',
|
||||||
alliance_ticker='a.t',
|
alliance_ticker='a.t',
|
||||||
executor_corp_id=5,
|
executor_corp_id=5,
|
||||||
)
|
)
|
||||||
EveCharacter.objects.create(
|
EveCharacter.objects.create(
|
||||||
character_id=1,
|
character_id=1,
|
||||||
character_name='character.name1',
|
character_name='character.name1',
|
||||||
corporation_id=2345,
|
corporation_id=2345,
|
||||||
corporation_name='character.corp.name',
|
corporation_name='character.corp.name',
|
||||||
corporation_ticker='c.c.t', # max 5 chars
|
corporation_ticker='c.c.t', # max 5 chars
|
||||||
alliance_id=None
|
alliance_id=None
|
||||||
)
|
)
|
||||||
EveCharacter.objects.create(
|
EveCharacter.objects.create(
|
||||||
@ -85,7 +85,7 @@ class TestRunModelUpdate(TestCase):
|
|||||||
character_name='character.name2',
|
character_name='character.name2',
|
||||||
corporation_id=9876,
|
corporation_id=9876,
|
||||||
corporation_name='character.corp.name',
|
corporation_name='character.corp.name',
|
||||||
corporation_ticker='c.c.t', # max 5 chars
|
corporation_ticker='c.c.t', # max 5 chars
|
||||||
alliance_id=3456,
|
alliance_id=3456,
|
||||||
alliance_name='character.alliance.name',
|
alliance_name='character.alliance.name',
|
||||||
)
|
)
|
||||||
@ -94,7 +94,7 @@ class TestRunModelUpdate(TestCase):
|
|||||||
character_name='character.name3',
|
character_name='character.name3',
|
||||||
corporation_id=9876,
|
corporation_id=9876,
|
||||||
corporation_name='character.corp.name',
|
corporation_name='character.corp.name',
|
||||||
corporation_ticker='c.c.t', # max 5 chars
|
corporation_ticker='c.c.t', # max 5 chars
|
||||||
alliance_id=3456,
|
alliance_id=3456,
|
||||||
alliance_name='character.alliance.name',
|
alliance_name='character.alliance.name',
|
||||||
)
|
)
|
||||||
@ -103,7 +103,7 @@ class TestRunModelUpdate(TestCase):
|
|||||||
character_name='character.name4',
|
character_name='character.name4',
|
||||||
corporation_id=9876,
|
corporation_id=9876,
|
||||||
corporation_name='character.corp.name',
|
corporation_name='character.corp.name',
|
||||||
corporation_ticker='c.c.t', # max 5 chars
|
corporation_ticker='c.c.t', # max 5 chars
|
||||||
alliance_id=3456,
|
alliance_id=3456,
|
||||||
alliance_name='character.alliance.name',
|
alliance_name='character.alliance.name',
|
||||||
)
|
)
|
||||||
@ -113,12 +113,12 @@ class TestRunModelUpdate(TestCase):
|
|||||||
character_name='character.name5',
|
character_name='character.name5',
|
||||||
corporation_id=9876,
|
corporation_id=9876,
|
||||||
corporation_name='character.corp.name',
|
corporation_name='character.corp.name',
|
||||||
corporation_ticker='c.c.t', # max 5 chars
|
corporation_ticker='c.c.t', # max 5 chars
|
||||||
alliance_id=3456,
|
alliance_id=3456,
|
||||||
alliance_name='character.alliance.name',
|
alliance_name='character.alliance.name',
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.affiliations = [
|
self.affiliations = [
|
||||||
{'character_id': 1, 'corporation_id': 5},
|
{'character_id': 1, 'corporation_id': 5},
|
||||||
@ -152,14 +152,14 @@ class TestRunModelUpdate(TestCase):
|
|||||||
|
|
||||||
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
||||||
= get_affiliations
|
= get_affiliations
|
||||||
|
|
||||||
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
||||||
|
|
||||||
run_model_update()
|
run_model_update()
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mock_provider.client.Character.post_characters_affiliation.call_count, 2
|
mock_provider.client.Character.post_characters_affiliation.call_count, 2
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mock_provider.client.Universe.post_universe_names.call_count, 2
|
mock_provider.client.Universe.post_universe_names.call_count, 2
|
||||||
)
|
)
|
||||||
@ -175,7 +175,7 @@ class TestRunModelUpdate(TestCase):
|
|||||||
self.assertEqual(mock_update_alliance.apply_async.call_count, 1)
|
self.assertEqual(mock_update_alliance.apply_async.call_count, 1)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
int(mock_update_alliance.apply_async.call_args[1]['args'][0]), 3456
|
int(mock_update_alliance.apply_async.call_args[1]['args'][0]), 3456
|
||||||
)
|
)
|
||||||
characters_updated = {
|
characters_updated = {
|
||||||
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
||||||
}
|
}
|
||||||
@ -203,9 +203,9 @@ class TestRunModelUpdate(TestCase):
|
|||||||
|
|
||||||
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
||||||
= get_affiliations
|
= get_affiliations
|
||||||
|
|
||||||
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
||||||
|
|
||||||
run_model_update()
|
run_model_update()
|
||||||
characters_updated = {
|
characters_updated = {
|
||||||
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
||||||
@ -234,9 +234,9 @@ class TestRunModelUpdate(TestCase):
|
|||||||
|
|
||||||
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
||||||
= get_affiliations
|
= get_affiliations
|
||||||
|
|
||||||
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
||||||
|
|
||||||
run_model_update()
|
run_model_update()
|
||||||
characters_updated = {
|
characters_updated = {
|
||||||
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
||||||
|
|||||||
@ -10,8 +10,8 @@ from django.dispatch import receiver
|
|||||||
from .models import AuthGroup
|
from .models import AuthGroup
|
||||||
from .models import GroupRequest
|
from .models import GroupRequest
|
||||||
|
|
||||||
if 'eve_autogroups' in apps.app_configs:
|
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
|
||||||
|
|
||||||
@ -20,12 +20,12 @@ class AuthGroupInlineAdmin(admin.StackedInline):
|
|||||||
model = AuthGroup
|
model = AuthGroup
|
||||||
filter_horizontal = ('group_leaders', 'group_leader_groups', 'states',)
|
filter_horizontal = ('group_leaders', 'group_leader_groups', 'states',)
|
||||||
fields = (
|
fields = (
|
||||||
'description',
|
'description',
|
||||||
'group_leaders',
|
'group_leaders',
|
||||||
'group_leader_groups',
|
'group_leader_groups',
|
||||||
'states', 'internal',
|
'states', 'internal',
|
||||||
'hidden',
|
'hidden',
|
||||||
'open',
|
'open',
|
||||||
'public'
|
'public'
|
||||||
)
|
)
|
||||||
verbose_name_plural = 'Auth Settings'
|
verbose_name_plural = 'Auth Settings'
|
||||||
@ -64,12 +64,12 @@ if _has_auto_groups:
|
|||||||
value = self.value()
|
value = self.value()
|
||||||
if value == 'yes':
|
if value == 'yes':
|
||||||
return queryset.exclude(
|
return queryset.exclude(
|
||||||
managedalliancegroup__isnull=True,
|
managedalliancegroup__isnull=True,
|
||||||
managedcorpgroup__isnull=True
|
managedcorpgroup__isnull=True
|
||||||
)
|
)
|
||||||
elif value == 'no':
|
elif value == 'no':
|
||||||
return queryset.filter(
|
return queryset.filter(
|
||||||
managedalliancegroup__isnull=True,
|
managedalliancegroup__isnull=True,
|
||||||
managedcorpgroup__isnull=True
|
managedcorpgroup__isnull=True
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -96,36 +96,36 @@ class HasLeaderFilter(admin.SimpleListFilter):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class GroupAdmin(admin.ModelAdmin):
|
class GroupAdmin(admin.ModelAdmin):
|
||||||
list_select_related = ('authgroup',)
|
list_select_related = ('authgroup',)
|
||||||
ordering = ('name',)
|
ordering = ('name',)
|
||||||
list_display = (
|
list_display = (
|
||||||
'name',
|
'name',
|
||||||
'_description',
|
'_description',
|
||||||
'_properties',
|
'_properties',
|
||||||
'_member_count',
|
'_member_count',
|
||||||
'has_leader'
|
'has_leader'
|
||||||
)
|
)
|
||||||
list_filter = [
|
list_filter = [
|
||||||
'authgroup__internal',
|
'authgroup__internal',
|
||||||
'authgroup__hidden',
|
'authgroup__hidden',
|
||||||
'authgroup__open',
|
'authgroup__open',
|
||||||
'authgroup__public',
|
'authgroup__public',
|
||||||
]
|
]
|
||||||
if _has_auto_groups:
|
if _has_auto_groups:
|
||||||
list_filter.append(IsAutoGroupFilter)
|
list_filter.append(IsAutoGroupFilter)
|
||||||
list_filter.append(HasLeaderFilter)
|
list_filter.append(HasLeaderFilter)
|
||||||
|
|
||||||
search_fields = ('name', 'authgroup__description')
|
search_fields = ('name', 'authgroup__description')
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super().get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
if _has_auto_groups:
|
if _has_auto_groups:
|
||||||
qs = qs.prefetch_related('managedalliancegroup_set', 'managedcorpgroup_set')
|
qs = qs.prefetch_related('managedalliancegroup_set', 'managedcorpgroup_set')
|
||||||
qs = qs.prefetch_related('authgroup__group_leaders')
|
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),
|
||||||
)
|
)
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
def _description(self, obj):
|
def _description(self, obj):
|
||||||
@ -136,16 +136,16 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
_member_count.short_description = 'Members'
|
_member_count.short_description = 'Members'
|
||||||
_member_count.admin_order_field = 'member_count'
|
_member_count.admin_order_field = 'member_count'
|
||||||
|
|
||||||
def has_leader(self, obj):
|
def has_leader(self, obj):
|
||||||
return obj.authgroup.group_leaders.exists()
|
return obj.authgroup.group_leaders.exists()
|
||||||
|
|
||||||
has_leader.boolean = True
|
has_leader.boolean = True
|
||||||
|
|
||||||
def _properties(self, obj):
|
def _properties(self, obj):
|
||||||
properties = list()
|
properties = list()
|
||||||
if _has_auto_groups and (
|
if _has_auto_groups and (
|
||||||
obj.managedalliancegroup_set.exists()
|
obj.managedalliancegroup_set.exists()
|
||||||
or obj.managedcorpgroup_set.exists()
|
or obj.managedcorpgroup_set.exists()
|
||||||
):
|
):
|
||||||
properties.append('Auto Group')
|
properties.append('Auto Group')
|
||||||
@ -160,7 +160,7 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
properties.append('Public')
|
properties.append('Public')
|
||||||
if not properties:
|
if not properties:
|
||||||
properties.append('Default')
|
properties.append('Default')
|
||||||
|
|
||||||
return properties
|
return properties
|
||||||
|
|
||||||
_properties.short_description = "properties"
|
_properties.short_description = "properties"
|
||||||
@ -183,19 +183,19 @@ finally:
|
|||||||
|
|
||||||
|
|
||||||
@admin.register(GroupRequest)
|
@admin.register(GroupRequest)
|
||||||
class GroupRequestAdmin(admin.ModelAdmin):
|
class GroupRequestAdmin(admin.ModelAdmin):
|
||||||
search_fields = ('user__username', )
|
search_fields = ('user__username', )
|
||||||
list_display = ('id', 'group', 'user', '_leave_request', 'status')
|
list_display = ('id', 'group', 'user', '_leave_request', 'status')
|
||||||
list_filter = (
|
list_filter = (
|
||||||
('group', admin.RelatedOnlyFieldListFilter),
|
('group', admin.RelatedOnlyFieldListFilter),
|
||||||
('user', admin.RelatedOnlyFieldListFilter),
|
('user', admin.RelatedOnlyFieldListFilter),
|
||||||
'leave_request',
|
'leave_request',
|
||||||
'status'
|
'status'
|
||||||
)
|
)
|
||||||
|
|
||||||
def _leave_request(self, obj) -> True:
|
def _leave_request(self, obj) -> True:
|
||||||
return obj.leave_request
|
return obj.leave_request
|
||||||
|
|
||||||
_leave_request.short_description = 'is leave request'
|
_leave_request.short_description = 'is leave request'
|
||||||
_leave_request.boolean = True
|
_leave_request.boolean = True
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class GroupManager:
|
class GroupManager:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_joinable_groups_for_user(
|
def get_joinable_groups_for_user(
|
||||||
cls, user: User, include_hidden = True
|
cls, user: User, include_hidden = True
|
||||||
@ -21,7 +21,7 @@ class GroupManager:
|
|||||||
|
|
||||||
if not user.has_perm('groupmanagement.request_groups'):
|
if not user.has_perm('groupmanagement.request_groups'):
|
||||||
groups_qs = groups_qs.filter(authgroup__public=True)
|
groups_qs = groups_qs.filter(authgroup__public=True)
|
||||||
|
|
||||||
if not include_hidden:
|
if not include_hidden:
|
||||||
groups_qs = groups_qs.filter(authgroup__hidden=False)
|
groups_qs = groups_qs.filter(authgroup__hidden=False)
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class GroupManager:
|
|||||||
:param state: allianceauth.authentication.State object
|
:param state: allianceauth.authentication.State object
|
||||||
:return: bool True if its joinable, False otherwise
|
:return: bool True if its joinable, False otherwise
|
||||||
"""
|
"""
|
||||||
if (len(group.authgroup.states.all()) != 0
|
if (len(group.authgroup.states.all()) != 0
|
||||||
and state not in group.authgroup.states.all()
|
and state not in group.authgroup.states.all()
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
@ -106,7 +106,7 @@ class GroupManager:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def pending_requests_count_for_user(cls, user: User) -> int:
|
def pending_requests_count_for_user(cls, user: User) -> int:
|
||||||
"""Returns the number of pending group requests for the given user"""
|
"""Returns the number of pending group requests for the given user"""
|
||||||
|
|
||||||
if cls.has_management_permission(user):
|
if cls.has_management_permission(user):
|
||||||
return GroupRequest.objects.filter(status="pending").count()
|
return GroupRequest.objects.filter(status="pending").count()
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -10,7 +10,7 @@ logger = logging.getLogger(__name__)
|
|||||||
def check_groups_on_state_change(sender, user, state, **kwargs):
|
def check_groups_on_state_change(sender, user, state, **kwargs):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Checking group memberships for %s based on new state %s" % (user, state)
|
"Checking group memberships for %s based on new state %s" % (user, state)
|
||||||
)
|
)
|
||||||
state_groups = (
|
state_groups = (
|
||||||
user.groups.select_related("authgroup").exclude(authgroup__states=None)
|
user.groups.select_related("authgroup").exclude(authgroup__states=None)
|
||||||
)
|
)
|
||||||
@ -18,5 +18,5 @@ def check_groups_on_state_change(sender, user, state, **kwargs):
|
|||||||
if not group.authgroup.states.filter(id=state.id).exists():
|
if not group.authgroup.states.filter(id=state.id).exists():
|
||||||
logger.info(
|
logger.info(
|
||||||
"Removing user %s from group %s due to missing state" % (user, group)
|
"Removing user %s from group %s due to missing state" % (user, group)
|
||||||
)
|
)
|
||||||
user.groups.remove(group)
|
user.groups.remove(group)
|
||||||
|
|||||||
@ -42,9 +42,9 @@
|
|||||||
|
|
||||||
<div class="panel panel-default panel-tabs-aa">
|
<div class="panel panel-default panel-tabs-aa">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
||||||
<div id="add" class="tab-pane active">
|
<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">
|
||||||
@ -98,9 +98,9 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<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 id="leave" class="tab-pane">
|
<div id="leave" class="tab-pane">
|
||||||
{% if leaverequests %}
|
{% if leaverequests %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-aa">
|
<table class="table table-aa">
|
||||||
|
|||||||
@ -26,7 +26,7 @@ MODULE_PATH = 'allianceauth.groupmanagement.admin'
|
|||||||
|
|
||||||
|
|
||||||
class MockRequest(object):
|
class MockRequest(object):
|
||||||
|
|
||||||
def __init__(self, user=None):
|
def __init__(self, user=None):
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
|
|
||||||
# group 1 - has leader
|
# group 1 - has leader
|
||||||
cls.group_1 = Group.objects.create(name='Group 1')
|
cls.group_1 = Group.objects.create(name='Group 1')
|
||||||
cls.group_1.authgroup.description = 'Default Group'
|
cls.group_1.authgroup.description = 'Default Group'
|
||||||
cls.group_1.authgroup.internal = False
|
cls.group_1.authgroup.internal = False
|
||||||
cls.group_1.authgroup.hidden = False
|
cls.group_1.authgroup.hidden = False
|
||||||
@ -47,7 +47,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
# group 2 - no leader
|
# group 2 - no leader
|
||||||
cls.group_2 = Group.objects.create(name='Group 2')
|
cls.group_2 = Group.objects.create(name='Group 2')
|
||||||
cls.group_2.authgroup.description = 'Internal Group'
|
cls.group_2.authgroup.description = 'Internal Group'
|
||||||
cls.group_2.authgroup.internal = True
|
cls.group_2.authgroup.internal = True
|
||||||
cls.group_2.authgroup.save()
|
cls.group_2.authgroup.save()
|
||||||
|
|
||||||
# group 3 - has leader
|
# group 3 - has leader
|
||||||
@ -81,7 +81,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
cls.group_6.authgroup.open = True
|
cls.group_6.authgroup.open = True
|
||||||
cls.group_6.authgroup.public = True
|
cls.group_6.authgroup.public = True
|
||||||
cls.group_6.authgroup.save()
|
cls.group_6.authgroup.save()
|
||||||
|
|
||||||
# user 1 - corp and alliance, normal user
|
# user 1 - corp and alliance, normal user
|
||||||
cls.character_1 = EveCharacter.objects.create(
|
cls.character_1 = EveCharacter.objects.create(
|
||||||
character_id=1001,
|
character_id=1001,
|
||||||
@ -106,16 +106,16 @@ class TestGroupAdmin(TestCase):
|
|||||||
alliance = EveAllianceInfo.objects.create(
|
alliance = EveAllianceInfo.objects.create(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
alliance_name='Wayne Enterprises',
|
alliance_name='Wayne Enterprises',
|
||||||
alliance_ticker='WE',
|
alliance_ticker='WE',
|
||||||
executor_corp_id=2001
|
executor_corp_id=2001
|
||||||
)
|
)
|
||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2001,
|
corporation_id=2001,
|
||||||
corporation_name='Wayne Technologies',
|
corporation_name='Wayne Technologies',
|
||||||
corporation_ticker='WT',
|
corporation_ticker='WT',
|
||||||
member_count=42,
|
member_count=42,
|
||||||
alliance=alliance
|
alliance=alliance
|
||||||
)
|
)
|
||||||
cls.user_1 = User.objects.create_user(
|
cls.user_1 = User.objects.create_user(
|
||||||
cls.character_1.character_name.replace(' ', '_'),
|
cls.character_1.character_name.replace(' ', '_'),
|
||||||
'abc@example.com',
|
'abc@example.com',
|
||||||
@ -148,7 +148,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2002,
|
corporation_id=2002,
|
||||||
corporation_name='Daily Plane',
|
corporation_name='Daily Plane',
|
||||||
corporation_ticker='DP',
|
corporation_ticker='DP',
|
||||||
member_count=99,
|
member_count=99,
|
||||||
alliance=None
|
alliance=None
|
||||||
)
|
)
|
||||||
@ -167,7 +167,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
cls.user_2.groups.add(cls.group_2)
|
cls.user_2.groups.add(cls.group_2)
|
||||||
cls.user_2.is_staff = True
|
cls.user_2.is_staff = True
|
||||||
cls.user_2.save()
|
cls.user_2.save()
|
||||||
|
|
||||||
# user 3 - no main, no group, superuser
|
# user 3 - no main, no group, superuser
|
||||||
cls.character_3 = EveCharacter.objects.create(
|
cls.character_3 = EveCharacter.objects.create(
|
||||||
character_id=1101,
|
character_id=1101,
|
||||||
@ -180,7 +180,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2101,
|
corporation_id=2101,
|
||||||
corporation_name='Lex Corp',
|
corporation_name='Lex Corp',
|
||||||
corporation_ticker='LC',
|
corporation_ticker='LC',
|
||||||
member_count=666,
|
member_count=666,
|
||||||
alliance=None
|
alliance=None
|
||||||
)
|
)
|
||||||
@ -222,7 +222,7 @@ class TestGroupAdmin(TestCase):
|
|||||||
for state in State.objects.all():
|
for state in State.objects.all():
|
||||||
autogroups_config.states.add(state)
|
autogroups_config.states.add(state)
|
||||||
autogroups_config.update_corp_group_membership(self.user_1)
|
autogroups_config.update_corp_group_membership(self.user_1)
|
||||||
|
|
||||||
# column rendering
|
# column rendering
|
||||||
|
|
||||||
def test_description(self):
|
def test_description(self):
|
||||||
@ -230,14 +230,14 @@ class TestGroupAdmin(TestCase):
|
|||||||
result = self.modeladmin._description(self.group_1)
|
result = self.modeladmin._description(self.group_1)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_member_count(self):
|
def test_member_count(self):
|
||||||
expected = 1
|
expected = 1
|
||||||
obj = self.modeladmin.get_queryset(MockRequest(user=self.user_1))\
|
obj = self.modeladmin.get_queryset(MockRequest(user=self.user_1))\
|
||||||
.get(pk=self.group_1.pk)
|
.get(pk=self.group_1.pk)
|
||||||
result = self.modeladmin._member_count(obj)
|
result = self.modeladmin._member_count(obj)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_has_leader(self):
|
def test_has_leader(self):
|
||||||
result = self.modeladmin.has_leader(self.group_1)
|
result = self.modeladmin.has_leader(self.group_1)
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
|
|
||||||
@ -283,17 +283,17 @@ class TestGroupAdmin(TestCase):
|
|||||||
self.assertListEqual(result, expected)
|
self.assertListEqual(result, expected)
|
||||||
|
|
||||||
# actions
|
# actions
|
||||||
|
|
||||||
# filters
|
# filters
|
||||||
|
|
||||||
if _has_auto_groups:
|
if _has_auto_groups:
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', True)
|
@patch(MODULE_PATH + '._has_auto_groups', True)
|
||||||
def test_filter_is_auto_group(self):
|
def test_filter_is_auto_group(self):
|
||||||
|
|
||||||
class GroupAdminTest(admin.ModelAdmin):
|
class GroupAdminTest(admin.ModelAdmin):
|
||||||
list_filter = (IsAutoGroupFilter,)
|
list_filter = (IsAutoGroupFilter,)
|
||||||
|
|
||||||
self._create_autogroups()
|
self._create_autogroups()
|
||||||
my_modeladmin = GroupAdminTest(Group, AdminSite())
|
my_modeladmin = GroupAdminTest(Group, AdminSite())
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
# Make sure the lookups are correct
|
||||||
@ -333,17 +333,17 @@ class TestGroupAdmin(TestCase):
|
|||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
queryset = changelist.get_queryset(request)
|
queryset = changelist.get_queryset(request)
|
||||||
expected = Group.objects.exclude(
|
expected = Group.objects.exclude(
|
||||||
managedalliancegroup__isnull=True,
|
managedalliancegroup__isnull=True,
|
||||||
managedcorpgroup__isnull=True
|
managedcorpgroup__isnull=True
|
||||||
)
|
)
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
self.assertSetEqual(set(queryset), set(expected))
|
||||||
|
|
||||||
def test_filter_has_leader(self):
|
def test_filter_has_leader(self):
|
||||||
|
|
||||||
class GroupAdminTest(admin.ModelAdmin):
|
class GroupAdminTest(admin.ModelAdmin):
|
||||||
list_filter = (HasLeaderFilter,)
|
list_filter = (HasLeaderFilter,)
|
||||||
|
|
||||||
self._create_autogroups()
|
self._create_autogroups()
|
||||||
my_modeladmin = GroupAdminTest(Group, AdminSite())
|
my_modeladmin = GroupAdminTest(Group, AdminSite())
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
# Make sure the lookups are correct
|
||||||
@ -378,16 +378,16 @@ class TestGroupAdmin(TestCase):
|
|||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
queryset = changelist.get_queryset(request)
|
queryset = changelist.get_queryset(request)
|
||||||
expected = [
|
expected = [
|
||||||
self.group_1,
|
self.group_1,
|
||||||
self.group_3
|
self.group_3
|
||||||
]
|
]
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
self.assertSetEqual(set(queryset), set(expected))
|
||||||
|
|
||||||
def test_change_view_loads_normally(self):
|
def test_change_view_loads_normally(self):
|
||||||
User.objects.create_superuser(
|
User.objects.create_superuser(
|
||||||
username='superuser', password='secret', email='admin@example.com'
|
username='superuser', password='secret', email='admin@example.com'
|
||||||
)
|
)
|
||||||
c = Client()
|
c = Client()
|
||||||
c.login(username='superuser', password='secret')
|
c.login(username='superuser', password='secret')
|
||||||
response = c.get(get_admin_change_view_url(self.group_1))
|
response = c.get(get_admin_change_view_url(self.group_1))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|||||||
@ -46,7 +46,7 @@ class GroupManagementVisibilityTestCase(TestCase):
|
|||||||
|
|
||||||
self.assertIn(self.group1, groups) #avail due to user
|
self.assertIn(self.group1, groups) #avail due to user
|
||||||
self.assertNotIn(self.group2, groups) #not avail due to group
|
self.assertNotIn(self.group2, groups) #not avail due to group
|
||||||
self.assertNotIn(self.group3, groups) #not avail at all
|
self.assertNotIn(self.group3, groups) #not avail at all
|
||||||
|
|
||||||
self.user.groups.add(self.group1)
|
self.user.groups.add(self.group1)
|
||||||
self._refresh_user()
|
self._refresh_user()
|
||||||
@ -60,7 +60,7 @@ class GroupManagementVisibilityTestCase(TestCase):
|
|||||||
self.assertTrue(GroupManager.can_manage_group(self.user, self.group1))
|
self.assertTrue(GroupManager.can_manage_group(self.user, self.group1))
|
||||||
self.assertFalse(GroupManager.can_manage_group(self.user, self.group2))
|
self.assertFalse(GroupManager.can_manage_group(self.user, self.group2))
|
||||||
self.assertFalse(GroupManager.can_manage_group(self.user, self.group3))
|
self.assertFalse(GroupManager.can_manage_group(self.user, self.group3))
|
||||||
|
|
||||||
self.group2.authgroup.group_leader_groups.add(self.group1)
|
self.group2.authgroup.group_leader_groups.add(self.group1)
|
||||||
self.group1.authgroup.group_leaders.remove(self.user)
|
self.group1.authgroup.group_leaders.remove(self.user)
|
||||||
self._refresh_user()
|
self._refresh_user()
|
||||||
@ -71,13 +71,13 @@ class GroupManagementVisibilityTestCase(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestGroupManager(TestCase):
|
class TestGroupManager(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
|
|
||||||
# group 1
|
# group 1
|
||||||
cls.group_default = Group.objects.create(name='default')
|
cls.group_default = Group.objects.create(name='default')
|
||||||
cls.group_default.authgroup.description = 'Default Group'
|
cls.group_default.authgroup.description = 'Default Group'
|
||||||
cls.group_default.authgroup.internal = False
|
cls.group_default.authgroup.internal = False
|
||||||
cls.group_default.authgroup.hidden = False
|
cls.group_default.authgroup.hidden = False
|
||||||
@ -86,7 +86,7 @@ class TestGroupManager(TestCase):
|
|||||||
# group 2
|
# group 2
|
||||||
cls.group_internal = Group.objects.create(name='internal')
|
cls.group_internal = Group.objects.create(name='internal')
|
||||||
cls.group_internal.authgroup.description = 'Internal Group'
|
cls.group_internal.authgroup.description = 'Internal Group'
|
||||||
cls.group_internal.authgroup.internal = True
|
cls.group_internal.authgroup.internal = True
|
||||||
cls.group_internal.authgroup.save()
|
cls.group_internal.authgroup.save()
|
||||||
|
|
||||||
# group 3
|
# group 3
|
||||||
@ -133,19 +133,19 @@ class TestGroupManager(TestCase):
|
|||||||
AuthUtils.get_member_state()
|
AuthUtils.get_member_state()
|
||||||
)
|
)
|
||||||
cls.group_default_member.authgroup.save()
|
cls.group_default_member.authgroup.save()
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = AuthUtils.create_user('Bruce Wayne')
|
self.user = AuthUtils.create_user('Bruce Wayne')
|
||||||
|
|
||||||
def test_get_joinable_group_member(self):
|
def test_get_joinable_group_member(self):
|
||||||
result = GroupManager.get_joinable_groups(
|
result = GroupManager.get_joinable_groups(
|
||||||
AuthUtils.get_member_state()
|
AuthUtils.get_member_state()
|
||||||
)
|
)
|
||||||
expected = {
|
expected = {
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_hidden,
|
self.group_hidden,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_public_2,
|
self.group_public_2,
|
||||||
self.group_default_member
|
self.group_default_member
|
||||||
}
|
}
|
||||||
@ -156,10 +156,10 @@ class TestGroupManager(TestCase):
|
|||||||
AuthUtils.get_guest_state()
|
AuthUtils.get_guest_state()
|
||||||
)
|
)
|
||||||
expected = {
|
expected = {
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_hidden,
|
self.group_hidden,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_public_2
|
self.group_public_2
|
||||||
}
|
}
|
||||||
self.assertSetEqual(set(result), expected)
|
self.assertSetEqual(set(result), expected)
|
||||||
@ -167,27 +167,27 @@ class TestGroupManager(TestCase):
|
|||||||
def test_joinable_group_member(self):
|
def test_joinable_group_member(self):
|
||||||
member_state = AuthUtils.get_member_state()
|
member_state = AuthUtils.get_member_state()
|
||||||
for x in [
|
for x in [
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_hidden,
|
self.group_hidden,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_public_2,
|
self.group_public_2,
|
||||||
self.group_default_member
|
self.group_default_member
|
||||||
]:
|
]:
|
||||||
self.assertTrue(GroupManager.joinable_group(x, member_state))
|
self.assertTrue(GroupManager.joinable_group(x, member_state))
|
||||||
|
|
||||||
for x in [
|
for x in [
|
||||||
self.group_internal,
|
self.group_internal,
|
||||||
]:
|
]:
|
||||||
self.assertFalse(GroupManager.joinable_group(x, member_state))
|
self.assertFalse(GroupManager.joinable_group(x, member_state))
|
||||||
|
|
||||||
def test_joinable_group_guest(self):
|
def test_joinable_group_guest(self):
|
||||||
guest_state = AuthUtils.get_guest_state()
|
guest_state = AuthUtils.get_guest_state()
|
||||||
for x in [
|
for x in [
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_hidden,
|
self.group_hidden,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_public_2
|
self.group_public_2
|
||||||
]:
|
]:
|
||||||
self.assertTrue(GroupManager.joinable_group(x, guest_state))
|
self.assertTrue(GroupManager.joinable_group(x, guest_state))
|
||||||
@ -201,11 +201,11 @@ class TestGroupManager(TestCase):
|
|||||||
def test_get_all_non_internal_groups(self):
|
def test_get_all_non_internal_groups(self):
|
||||||
result = GroupManager.get_all_non_internal_groups()
|
result = GroupManager.get_all_non_internal_groups()
|
||||||
expected = {
|
expected = {
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_hidden,
|
self.group_hidden,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_public_2,
|
self.group_public_2,
|
||||||
self.group_default_member
|
self.group_default_member
|
||||||
}
|
}
|
||||||
self.assertSetEqual(set(result), expected)
|
self.assertSetEqual(set(result), expected)
|
||||||
@ -231,10 +231,10 @@ class TestGroupManager(TestCase):
|
|||||||
)
|
)
|
||||||
result = GroupManager.get_joinable_groups_for_user(self.user)
|
result = GroupManager.get_joinable_groups_for_user(self.user)
|
||||||
expected = {
|
expected = {
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_hidden,
|
self.group_hidden,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_public_2
|
self.group_public_2
|
||||||
}
|
}
|
||||||
self.assertSetEqual(set(result), expected)
|
self.assertSetEqual(set(result), expected)
|
||||||
@ -265,69 +265,69 @@ class TestGroupManager(TestCase):
|
|||||||
)
|
)
|
||||||
expected = {
|
expected = {
|
||||||
self.group_default,
|
self.group_default,
|
||||||
self.group_open,
|
self.group_open,
|
||||||
self.group_public_1,
|
self.group_public_1,
|
||||||
self.group_default_member
|
self.group_default_member
|
||||||
}
|
}
|
||||||
self.assertSetEqual(set(result), expected)
|
self.assertSetEqual(set(result), expected)
|
||||||
|
|
||||||
def test_has_management_permission(self):
|
def test_has_management_permission(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
AuthUtils.add_permission_to_user_by_name(
|
AuthUtils.add_permission_to_user_by_name(
|
||||||
'auth.group_management', user
|
'auth.group_management', user
|
||||||
)
|
)
|
||||||
self.assertTrue(GroupManager.has_management_permission(user))
|
self.assertTrue(GroupManager.has_management_permission(user))
|
||||||
|
|
||||||
def test_can_manage_groups_no_perm_no_group(self):
|
def test_can_manage_groups_no_perm_no_group(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
self.assertFalse(GroupManager.can_manage_groups(user))
|
self.assertFalse(GroupManager.can_manage_groups(user))
|
||||||
|
|
||||||
def test_can_manage_groups_user_not_authenticated(self):
|
def test_can_manage_groups_user_not_authenticated(self):
|
||||||
user = MockUserNotAuthenticated()
|
user = MockUserNotAuthenticated()
|
||||||
self.assertFalse(GroupManager.can_manage_groups(user))
|
self.assertFalse(GroupManager.can_manage_groups(user))
|
||||||
|
|
||||||
def test_can_manage_groups_has_perm(self):
|
def test_can_manage_groups_has_perm(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
AuthUtils.add_permission_to_user_by_name(
|
AuthUtils.add_permission_to_user_by_name(
|
||||||
'auth.group_management', user
|
'auth.group_management', user
|
||||||
)
|
)
|
||||||
self.assertTrue(GroupManager.can_manage_groups(user))
|
self.assertTrue(GroupManager.can_manage_groups(user))
|
||||||
|
|
||||||
def test_can_manage_groups_no_perm_leads_group(self):
|
def test_can_manage_groups_no_perm_leads_group(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
self.group_default.authgroup.group_leaders.add(user)
|
self.group_default.authgroup.group_leaders.add(user)
|
||||||
self.assertTrue(GroupManager.can_manage_groups(user))
|
self.assertTrue(GroupManager.can_manage_groups(user))
|
||||||
|
|
||||||
def test_can_manage_group_no_perm_no_group(self):
|
def test_can_manage_group_no_perm_no_group(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
GroupManager.can_manage_group(user, self.group_default)
|
GroupManager.can_manage_group(user, self.group_default)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_manage_group_has_perm(self):
|
def test_can_manage_group_has_perm(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
AuthUtils.add_permission_to_user_by_name(
|
AuthUtils.add_permission_to_user_by_name(
|
||||||
'auth.group_management', user
|
'auth.group_management', user
|
||||||
)
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
GroupManager.can_manage_group(user, self.group_default)
|
GroupManager.can_manage_group(user, self.group_default)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_manage_group_no_perm_leads_correct_group(self):
|
def test_can_manage_group_no_perm_leads_correct_group(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
self.group_default.authgroup.group_leaders.add(user)
|
self.group_default.authgroup.group_leaders.add(user)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
GroupManager.can_manage_group(user, self.group_default)
|
GroupManager.can_manage_group(user, self.group_default)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_manage_group_no_perm_leads_other_group(self):
|
def test_can_manage_group_no_perm_leads_other_group(self):
|
||||||
user = AuthUtils.create_user('Clark Kent')
|
user = AuthUtils.create_user('Clark Kent')
|
||||||
self.group_hidden.authgroup.group_leaders.add(user)
|
self.group_hidden.authgroup.group_leaders.add(user)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
GroupManager.can_manage_group(user, self.group_default)
|
GroupManager.can_manage_group(user, self.group_default)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_manage_group_user_not_authenticated(self):
|
def test_can_manage_group_user_not_authenticated(self):
|
||||||
user = MockUserNotAuthenticated()
|
user = MockUserNotAuthenticated()
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
GroupManager.can_manage_group(user, self.group_default)
|
GroupManager.can_manage_group(user, self.group_default)
|
||||||
@ -335,7 +335,7 @@ class TestGroupManager(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestPendingRequestsCountForUser(TestCase):
|
class TestPendingRequestsCountForUser(TestCase):
|
||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self.group_1 = Group.objects.create(name="Group 1")
|
self.group_1 = Group.objects.create(name="Group 1")
|
||||||
self.group_2 = Group.objects.create(name="Group 2")
|
self.group_2 = Group.objects.create(name="Group 2")
|
||||||
@ -345,8 +345,8 @@ class TestPendingRequestsCountForUser(TestCase):
|
|||||||
self.group_2.authgroup.group_leaders.add(self.user_leader_2)
|
self.group_2.authgroup.group_leaders.add(self.user_leader_2)
|
||||||
self.user_requestor = AuthUtils.create_member('Bruce Wayne')
|
self.user_requestor = AuthUtils.create_member('Bruce Wayne')
|
||||||
|
|
||||||
def test_single_request_for_leader(self):
|
def test_single_request_for_leader(self):
|
||||||
# given user_leader_1 is leader of group_1
|
# given user_leader_1 is leader of group_1
|
||||||
# and user_leader_2 is leader of group_2
|
# and user_leader_2 is leader of group_2
|
||||||
# when user_requestor is requesting access to group 1
|
# when user_requestor is requesting access to group 1
|
||||||
# then return 1 for user_leader 1 and 0 for user_leader_2
|
# then return 1 for user_leader 1 and 0 for user_leader_2
|
||||||
@ -359,7 +359,7 @@ class TestPendingRequestsCountForUser(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
GroupManager.pending_requests_count_for_user(self.user_leader_2), 0
|
GroupManager.pending_requests_count_for_user(self.user_leader_2), 0
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_return_none_for_none_leader(self):
|
def test_return_none_for_none_leader(self):
|
||||||
# given user_requestor is leader of no group
|
# given user_requestor is leader of no group
|
||||||
# when user_requestor is requesting access to group 1
|
# when user_requestor is requesting access to group 1
|
||||||
@ -370,7 +370,7 @@ class TestPendingRequestsCountForUser(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
GroupManager.pending_requests_count_for_user(self.user_requestor), 0
|
GroupManager.pending_requests_count_for_user(self.user_requestor), 0
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_single_leave_request(self):
|
def test_single_leave_request(self):
|
||||||
# given user_leader_2 is leader of group_2
|
# given user_leader_2 is leader of group_2
|
||||||
# and user_requestor is member of group 2
|
# and user_requestor is member of group 2
|
||||||
@ -379,9 +379,9 @@ class TestPendingRequestsCountForUser(TestCase):
|
|||||||
self.user_requestor.groups.add(self.group_2)
|
self.user_requestor.groups.add(self.group_2)
|
||||||
|
|
||||||
GroupRequest.objects.create(
|
GroupRequest.objects.create(
|
||||||
status="pending",
|
status="pending",
|
||||||
user=self.user_requestor,
|
user=self.user_requestor,
|
||||||
group=self.group_2,
|
group=self.group_2,
|
||||||
leave_request=True
|
leave_request=True
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -391,31 +391,31 @@ class TestPendingRequestsCountForUser(TestCase):
|
|||||||
def test_join_and_leave_request(self):
|
def test_join_and_leave_request(self):
|
||||||
# given user_leader_2 is leader of group_2
|
# given user_leader_2 is leader of group_2
|
||||||
# and user_requestor is member of group 2
|
# and user_requestor is member of group 2
|
||||||
# when user_requestor is requesting to leave group 2
|
# when user_requestor is requesting to leave group 2
|
||||||
# and user_requestor_2 is requesting to join group 2
|
# and user_requestor_2 is requesting to join group 2
|
||||||
# then return 2 for user_leader_2
|
# then return 2 for user_leader_2
|
||||||
self.user_requestor.groups.add(self.group_2)
|
self.user_requestor.groups.add(self.group_2)
|
||||||
user_requestor_2 = AuthUtils.create_member("Lex Luther")
|
user_requestor_2 = AuthUtils.create_member("Lex Luther")
|
||||||
GroupRequest.objects.create(
|
GroupRequest.objects.create(
|
||||||
status="pending",
|
status="pending",
|
||||||
user=user_requestor_2,
|
user=user_requestor_2,
|
||||||
group=self.group_2
|
group=self.group_2
|
||||||
)
|
)
|
||||||
GroupRequest.objects.create(
|
GroupRequest.objects.create(
|
||||||
status="pending",
|
status="pending",
|
||||||
user=self.user_requestor,
|
user=self.user_requestor,
|
||||||
group=self.group_2,
|
group=self.group_2,
|
||||||
leave_request=True
|
leave_request=True
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
GroupManager.pending_requests_count_for_user(self.user_leader_2), 2
|
GroupManager.pending_requests_count_for_user(self.user_leader_2), 2
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_single_request_for_user_with_management_perm(self):
|
def test_single_request_for_user_with_management_perm(self):
|
||||||
# given user_leader_4 which is leafer of no group
|
# given user_leader_4 which is leafer of no group
|
||||||
# but has the management permissions
|
# but has the management permissions
|
||||||
# when user_requestor is requesting access to group 1
|
# when user_requestor is requesting access to group 1
|
||||||
# then return 1 for user_leader_4
|
# then return 1 for user_leader_4
|
||||||
user_leader_4 = AuthUtils.create_member("Lex Luther")
|
user_leader_4 = AuthUtils.create_member("Lex Luther")
|
||||||
AuthUtils.add_permission_to_user_by_name("auth.group_management", user_leader_4)
|
AuthUtils.add_permission_to_user_by_name("auth.group_management", user_leader_4)
|
||||||
user_leader_4 = User.objects.get(pk=user_leader_4.pk)
|
user_leader_4 = User.objects.get(pk=user_leader_4.pk)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from allianceauth.eveonline.models import (
|
|||||||
from ..models import GroupRequest, RequestLog
|
from ..models import GroupRequest, RequestLog
|
||||||
|
|
||||||
|
|
||||||
def create_testdata():
|
def create_testdata():
|
||||||
# clear DB
|
# clear DB
|
||||||
User.objects.all().delete()
|
User.objects.all().delete()
|
||||||
Group.objects.all().delete()
|
Group.objects.all().delete()
|
||||||
@ -20,13 +20,13 @@ def create_testdata():
|
|||||||
EveAllianceInfo.objects.all().delete()
|
EveAllianceInfo.objects.all().delete()
|
||||||
|
|
||||||
# group 1
|
# group 1
|
||||||
group = Group.objects.create(name='Superheros')
|
group = Group.objects.create(name='Superheros')
|
||||||
group.authgroup.description = 'Default Group'
|
group.authgroup.description = 'Default Group'
|
||||||
group.authgroup.internal = False
|
group.authgroup.internal = False
|
||||||
group.authgroup.hidden = False
|
group.authgroup.hidden = False
|
||||||
group.authgroup.save()
|
group.authgroup.save()
|
||||||
|
|
||||||
# user 1
|
# user 1
|
||||||
user_1 = AuthUtils.create_user('Bruce Wayne')
|
user_1 = AuthUtils.create_user('Bruce Wayne')
|
||||||
AuthUtils.add_main_character_2(
|
AuthUtils.add_main_character_2(
|
||||||
user_1,
|
user_1,
|
||||||
@ -34,7 +34,7 @@ def create_testdata():
|
|||||||
character_id=1001,
|
character_id=1001,
|
||||||
corp_id=2001,
|
corp_id=2001,
|
||||||
corp_name='Wayne Technologies'
|
corp_name='Wayne Technologies'
|
||||||
)
|
)
|
||||||
user_1.groups.add(group)
|
user_1.groups.add(group)
|
||||||
group.authgroup.group_leaders.add(user_1)
|
group.authgroup.group_leaders.add(user_1)
|
||||||
|
|
||||||
@ -46,13 +46,13 @@ def create_testdata():
|
|||||||
character_id=1002,
|
character_id=1002,
|
||||||
corp_id=2002,
|
corp_id=2002,
|
||||||
corp_name='Wayne Technologies'
|
corp_name='Wayne Technologies'
|
||||||
)
|
)
|
||||||
return group, user_1, user_2
|
return group, user_1, user_2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestGroupRequest(TestCase):
|
class TestGroupRequest(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
@ -78,7 +78,7 @@ class TestGroupRequest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestRequestLog(TestCase):
|
class TestRequestLog(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
@ -124,7 +124,7 @@ class TestRequestLog(TestCase):
|
|||||||
self.assertEqual(request_log.type_to_str(), expected)
|
self.assertEqual(request_log.type_to_str(), expected)
|
||||||
|
|
||||||
def test_action_to_str_accept(self):
|
def test_action_to_str_accept(self):
|
||||||
request_log = RequestLog.objects.create(
|
request_log = RequestLog.objects.create(
|
||||||
group=self.group,
|
group=self.group,
|
||||||
request_info='Clark Kent:Superheros',
|
request_info='Clark Kent:Superheros',
|
||||||
request_actor=self.user_1,
|
request_actor=self.user_1,
|
||||||
@ -134,7 +134,7 @@ class TestRequestLog(TestCase):
|
|||||||
self.assertEqual(request_log.action_to_str(), expected)
|
self.assertEqual(request_log.action_to_str(), expected)
|
||||||
|
|
||||||
def test_action_to_str_reject(self):
|
def test_action_to_str_reject(self):
|
||||||
request_log = RequestLog.objects.create(
|
request_log = RequestLog.objects.create(
|
||||||
group=self.group,
|
group=self.group,
|
||||||
request_info='Clark Kent:Superheros',
|
request_info='Clark Kent:Superheros',
|
||||||
request_actor=self.user_1,
|
request_actor=self.user_1,
|
||||||
@ -144,7 +144,7 @@ class TestRequestLog(TestCase):
|
|||||||
self.assertEqual(request_log.action_to_str(), expected)
|
self.assertEqual(request_log.action_to_str(), expected)
|
||||||
|
|
||||||
def test_req_char(self):
|
def test_req_char(self):
|
||||||
request_log = RequestLog.objects.create(
|
request_log = RequestLog.objects.create(
|
||||||
group=self.group,
|
group=self.group,
|
||||||
request_info='Clark Kent:Superheros',
|
request_info='Clark Kent:Superheros',
|
||||||
request_actor=self.user_1,
|
request_actor=self.user_1,
|
||||||
@ -157,7 +157,7 @@ class TestRequestLog(TestCase):
|
|||||||
class TestAuthGroup(TestCase):
|
class TestAuthGroup(TestCase):
|
||||||
|
|
||||||
def test_str(self):
|
def test_str(self):
|
||||||
group = Group.objects.create(name='Superheros')
|
group = Group.objects.create(name='Superheros')
|
||||||
group.authgroup.description = 'Default Group'
|
group.authgroup.description = 'Default Group'
|
||||||
group.authgroup.internal = False
|
group.authgroup.internal = False
|
||||||
group.authgroup.hidden = False
|
group.authgroup.hidden = False
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class TestCheckGroupsOnStateChange(TestCase):
|
|||||||
cls.character = AuthUtils.add_main_character_2(
|
cls.character = AuthUtils.add_main_character_2(
|
||||||
cls.user, 'test character', 1001, corp_id=2001, corp_name='test corp 1', corp_ticker='TEST'
|
cls.user, 'test character', 1001, corp_id=2001, corp_name='test corp 1', corp_ticker='TEST'
|
||||||
)
|
)
|
||||||
cls.user.profile.refresh_from_db()
|
cls.user.profile.refresh_from_db()
|
||||||
cls.corp_1 = EveCorporationInfo.objects.create(
|
cls.corp_1 = EveCorporationInfo.objects.create(
|
||||||
corporation_id=2001, corporation_name='test corp 1', corporation_ticker='C1', member_count=1
|
corporation_id=2001, corporation_name='test corp 1', corporation_ticker='C1', member_count=1
|
||||||
)
|
)
|
||||||
@ -24,13 +24,13 @@ class TestCheckGroupsOnStateChange(TestCase):
|
|||||||
cls.guest_state = AuthUtils.get_guest_state()
|
cls.guest_state = AuthUtils.get_guest_state()
|
||||||
cls.test_state_1 = AuthUtils.create_state('test_state_1', 500)
|
cls.test_state_1 = AuthUtils.create_state('test_state_1', 500)
|
||||||
cls.test_state_2 = AuthUtils.create_state('test_state_2', 600)
|
cls.test_state_2 = AuthUtils.create_state('test_state_2', 600)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
|
|
||||||
def _refresh_user(self):
|
def _refresh_user(self):
|
||||||
self.user = User.objects.get(pk=self.user.pk)
|
self.user = User.objects.get(pk=self.user.pk)
|
||||||
|
|
||||||
def test_drop_state_group(self):
|
def test_drop_state_group(self):
|
||||||
"""
|
"""
|
||||||
given user is member of: state group, normal group and auto group
|
given user is member of: state group, normal group and auto group
|
||||||
@ -39,29 +39,29 @@ class TestCheckGroupsOnStateChange(TestCase):
|
|||||||
and remains member of normal group and auto group
|
and remains member of normal group and auto group
|
||||||
"""
|
"""
|
||||||
# setup
|
# setup
|
||||||
state_group = Group.objects.create(name='state_group')
|
state_group = Group.objects.create(name='state_group')
|
||||||
state_group.authgroup.states.add(self.test_state_1)
|
state_group.authgroup.states.add(self.test_state_1)
|
||||||
state_group.authgroup.internal = False
|
state_group.authgroup.internal = False
|
||||||
state_group.save()
|
state_group.save()
|
||||||
normal_group = Group.objects.create(name='normal_group')
|
normal_group = Group.objects.create(name='normal_group')
|
||||||
normal_group.authgroup.internal = False
|
normal_group.authgroup.internal = False
|
||||||
normal_group.save()
|
normal_group.save()
|
||||||
internal_group = Group.objects.create(name='internal_group')
|
internal_group = Group.objects.create(name='internal_group')
|
||||||
autogroup_config = AutogroupsConfig.objects.create(corp_groups=True)
|
autogroup_config = AutogroupsConfig.objects.create(corp_groups=True)
|
||||||
autogroup_config.states.add(self.test_state_1)
|
autogroup_config.states.add(self.test_state_1)
|
||||||
autogroup_config.states.add(self.guest_state)
|
autogroup_config.states.add(self.guest_state)
|
||||||
auto_group = autogroup_config.corp_managed_groups.first()
|
auto_group = autogroup_config.corp_managed_groups.first()
|
||||||
internal_state_group = Group.objects.create(name='internal_state_group')
|
internal_state_group = Group.objects.create(name='internal_state_group')
|
||||||
internal_state_group.authgroup.states.add(self.test_state_1)
|
internal_state_group.authgroup.states.add(self.test_state_1)
|
||||||
self.test_state_1.member_corporations.add(self.corp_1)
|
self.test_state_1.member_corporations.add(self.corp_1)
|
||||||
self.user.groups.add(normal_group)
|
self.user.groups.add(normal_group)
|
||||||
self.user.groups.add(internal_group)
|
self.user.groups.add(internal_group)
|
||||||
self.user.groups.add(state_group)
|
self.user.groups.add(state_group)
|
||||||
self.user.groups.add(internal_state_group)
|
self.user.groups.add(internal_state_group)
|
||||||
|
|
||||||
# user changes state back to guest
|
# user changes state back to guest
|
||||||
self.test_state_1.member_corporations.clear()
|
self.test_state_1.member_corporations.clear()
|
||||||
|
|
||||||
# assert
|
# assert
|
||||||
self._refresh_user()
|
self._refresh_user()
|
||||||
self.assertEqual(self.user.profile.state, self.guest_state)
|
self.assertEqual(self.user.profile.state, self.guest_state)
|
||||||
@ -79,22 +79,21 @@ class TestCheckGroupsOnStateChange(TestCase):
|
|||||||
then user remains member of that group
|
then user remains member of that group
|
||||||
"""
|
"""
|
||||||
# setup
|
# setup
|
||||||
state_group = Group.objects.create(name='state_group')
|
state_group = Group.objects.create(name='state_group')
|
||||||
state_group.authgroup.states.add(self.test_state_1)
|
state_group.authgroup.states.add(self.test_state_1)
|
||||||
state_group.authgroup.states.add(self.test_state_2)
|
state_group.authgroup.states.add(self.test_state_2)
|
||||||
|
|
||||||
self.test_state_1.member_corporations.add(self.corp_1)
|
self.test_state_1.member_corporations.add(self.corp_1)
|
||||||
self.test_state_2.member_corporations.add(self.corp_2)
|
self.test_state_2.member_corporations.add(self.corp_2)
|
||||||
self.user.groups.add(state_group)
|
self.user.groups.add(state_group)
|
||||||
|
|
||||||
# user changes state back to guest
|
# user changes state back to guest
|
||||||
self.character.corporation_id = 2002
|
self.character.corporation_id = 2002
|
||||||
self.character.corporation_name = "test corp 2"
|
self.character.corporation_name = "test corp 2"
|
||||||
self.character.save()
|
self.character.save()
|
||||||
|
|
||||||
# assert
|
# assert
|
||||||
self._refresh_user()
|
self._refresh_user()
|
||||||
self.assertEqual(self.user.profile.state, self.test_state_2)
|
self.assertEqual(self.user.profile.state, self.test_state_2)
|
||||||
groups = self.user.groups.all()
|
groups = self.user.groups.all()
|
||||||
self.assertIn(state_group, groups)
|
self.assertIn(state_group, groups)
|
||||||
|
|
||||||
@ -10,13 +10,13 @@ from .. import views
|
|||||||
|
|
||||||
|
|
||||||
class TestViews(TestCase):
|
class TestViews(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.factory = RequestFactory()
|
self.factory = RequestFactory()
|
||||||
self.user = AuthUtils.create_user('Bruce Wayne')
|
self.user = AuthUtils.create_user('Bruce Wayne')
|
||||||
|
|
||||||
def test_groups_view_can_load(self):
|
def test_groups_view_can_load(self):
|
||||||
request = self.factory.get(reverse('groupmanagement:groups'))
|
request = self.factory.get(reverse('groupmanagement:groups'))
|
||||||
request.user = self.user
|
request.user = self.user
|
||||||
response = views.groups_view(request)
|
response = views.groups_view(request)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
@ -15,11 +15,11 @@ class ApplicationsMenu(MenuItemHook):
|
|||||||
'hrapplications:index',
|
'hrapplications:index',
|
||||||
navactive=['hrapplications:'])
|
navactive=['hrapplications:'])
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
app_count = Application.objects.pending_requests_count_for_user(request.user)
|
app_count = Application.objects.pending_requests_count_for_user(request.user)
|
||||||
self.count = app_count if app_count and app_count > 0 else None
|
self.count = app_count if app_count and app_count > 0 else None
|
||||||
return MenuItemHook.render(self, request)
|
return MenuItemHook.render(self, request)
|
||||||
|
|
||||||
|
|
||||||
@hooks.register('menu_item_hook')
|
@hooks.register('menu_item_hook')
|
||||||
def register_menu():
|
def register_menu():
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class NotificationManager(models.Manager):
|
|||||||
|
|
||||||
USER_NOTIFICATION_COUNT_PREFIX = 'USER_NOTIFICATION_COUNT'
|
USER_NOTIFICATION_COUNT_PREFIX = 'USER_NOTIFICATION_COUNT'
|
||||||
USER_NOTIFICATION_COUNT_CACHE_DURATION = 86_400
|
USER_NOTIFICATION_COUNT_CACHE_DURATION = 86_400
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return NotificationQuerySet(self.model, using=self._db)
|
return NotificationQuerySet(self.model, using=self._db)
|
||||||
|
|
||||||
@ -39,37 +39,37 @@ class NotificationManager(models.Manager):
|
|||||||
)[max_notifications - 1:]
|
)[max_notifications - 1:]
|
||||||
for notification in to_be_deleted_qs:
|
for notification in to_be_deleted_qs:
|
||||||
notification.delete()
|
notification.delete()
|
||||||
|
|
||||||
if not message:
|
if not message:
|
||||||
message = title
|
message = title
|
||||||
|
|
||||||
obj = self.create(user=user, title=title, message=message, level=level)
|
obj = self.create(user=user, title=title, message=message, level=level)
|
||||||
logger.info("Created notification %s", obj)
|
logger.info("Created notification %s", obj)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def _max_notifications_per_user(self):
|
def _max_notifications_per_user(self):
|
||||||
"""return the maximum number of notifications allowed per user"""
|
"""return the maximum number of notifications allowed per user"""
|
||||||
max_notifications = getattr(settings, 'NOTIFICATIONS_MAX_PER_USER', None)
|
max_notifications = getattr(settings, 'NOTIFICATIONS_MAX_PER_USER', None)
|
||||||
if (
|
if (
|
||||||
max_notifications is None
|
max_notifications is None
|
||||||
or not isinstance(max_notifications, int)
|
or not isinstance(max_notifications, int)
|
||||||
or max_notifications < 0
|
or max_notifications < 0
|
||||||
):
|
):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'NOTIFICATIONS_MAX_PER_USER setting is invalid. Using default.'
|
'NOTIFICATIONS_MAX_PER_USER setting is invalid. Using default.'
|
||||||
)
|
)
|
||||||
max_notifications = self.model.NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
max_notifications = self.model.NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
||||||
|
|
||||||
return max_notifications
|
return max_notifications
|
||||||
|
|
||||||
def user_unread_count(self, user_pk: int) -> int:
|
def user_unread_count(self, user_pk: int) -> int:
|
||||||
"""returns the cached unread count for a user given by user PK
|
"""returns the cached unread count for a user given by user PK
|
||||||
|
|
||||||
Will return -1 if user can not be found
|
Will return -1 if user can not be found
|
||||||
"""
|
"""
|
||||||
cache_key = self._user_notification_cache_key(user_pk)
|
cache_key = self._user_notification_cache_key(user_pk)
|
||||||
unread_count = cache.get(key=cache_key)
|
unread_count = cache.get(key=cache_key)
|
||||||
if not unread_count:
|
if not unread_count:
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(pk=user_pk)
|
user = User.objects.get(pk=user_pk)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
@ -80,8 +80,8 @@ class NotificationManager(models.Manager):
|
|||||||
)
|
)
|
||||||
unread_count = user.notification_set.filter(viewed=False).count()
|
unread_count = user.notification_set.filter(viewed=False).count()
|
||||||
cache.set(
|
cache.set(
|
||||||
key=cache_key,
|
key=cache_key,
|
||||||
value=unread_count,
|
value=unread_count,
|
||||||
timeout=self.USER_NOTIFICATION_COUNT_CACHE_DURATION
|
timeout=self.USER_NOTIFICATION_COUNT_CACHE_DURATION
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -92,7 +92,7 @@ class NotificationManager(models.Manager):
|
|||||||
return unread_count
|
return unread_count
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def invalidate_user_notification_cache(cls, user_pk: int) -> None:
|
def invalidate_user_notification_cache(cls, user_pk: int) -> None:
|
||||||
cache.delete(key=cls._user_notification_cache_key(user_pk))
|
cache.delete(key=cls._user_notification_cache_key(user_pk))
|
||||||
logger.debug('Invalided notification cache for user with pk %s', user_pk)
|
logger.debug('Invalided notification cache for user with pk %s', user_pk)
|
||||||
|
|
||||||
|
|||||||
@ -10,10 +10,10 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class Notification(models.Model):
|
class Notification(models.Model):
|
||||||
"""Notification to a user within Auth"""
|
"""Notification to a user within Auth"""
|
||||||
|
|
||||||
NOTIFICATIONS_MAX_PER_USER_DEFAULT = 50
|
NOTIFICATIONS_MAX_PER_USER_DEFAULT = 50
|
||||||
NOTIFICATIONS_REFRESH_TIME_DEFAULT = 30
|
NOTIFICATIONS_REFRESH_TIME_DEFAULT = 30
|
||||||
|
|
||||||
LEVEL_CHOICES = (
|
LEVEL_CHOICES = (
|
||||||
('danger', 'CRITICAL'),
|
('danger', 'CRITICAL'),
|
||||||
('danger', 'ERROR'),
|
('danger', 'ERROR'),
|
||||||
@ -30,18 +30,18 @@ class Notification(models.Model):
|
|||||||
viewed = models.BooleanField(default=False, db_index=True)
|
viewed = models.BooleanField(default=False, db_index=True)
|
||||||
|
|
||||||
objects = NotificationManager()
|
objects = NotificationManager()
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return "%s: %s" % (self.user, self.title)
|
return "%s: %s" % (self.user, self.title)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
# overriden save to ensure cache is invaidated on very call
|
# overriden save to ensure cache is invaidated on very call
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
# overriden delete to ensure cache is invaidated on very call
|
# overriden delete to ensure cache is invaidated on very call
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
||||||
|
|
||||||
def mark_viewed(self) -> None:
|
def mark_viewed(self) -> None:
|
||||||
@ -52,7 +52,7 @@ class Notification(models.Model):
|
|||||||
|
|
||||||
def set_level(self, level_name: str) -> None:
|
def set_level(self, level_name: str) -> None:
|
||||||
"""set notification level according to level name, e.g. 'CRITICAL'
|
"""set notification level according to level name, e.g. 'CRITICAL'
|
||||||
|
|
||||||
raised exception on invalid level names
|
raised exception on invalid level names
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -20,7 +20,7 @@ register = template.Library()
|
|||||||
@register.filter
|
@register.filter
|
||||||
def user_unread_notification_count(user: object) -> int:
|
def user_unread_notification_count(user: object) -> int:
|
||||||
"""returns the number of unread notifications for user
|
"""returns the number of unread notifications for user
|
||||||
|
|
||||||
Will return -1 on error
|
Will return -1 on error
|
||||||
"""
|
"""
|
||||||
if not isinstance(user, User):
|
if not isinstance(user, User):
|
||||||
@ -29,10 +29,10 @@ def user_unread_notification_count(user: object) -> int:
|
|||||||
unread_count = Notification.objects.user_unread_count(user.pk)
|
unread_count = Notification.objects.user_unread_count(user.pk)
|
||||||
|
|
||||||
return unread_count
|
return unread_count
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def notifications_refresh_time() -> int:
|
def notifications_refresh_time() -> int:
|
||||||
refresh_time = getattr(settings, 'NOTIFICATIONS_REFRESH_TIME', Notification.NOTIFICATIONS_REFRESH_TIME_DEFAULT)
|
refresh_time = getattr(settings, 'NOTIFICATIONS_REFRESH_TIME', Notification.NOTIFICATIONS_REFRESH_TIME_DEFAULT)
|
||||||
if (not isinstance(refresh_time, int) or refresh_time < 0):
|
if (not isinstance(refresh_time, int) or refresh_time < 0):
|
||||||
logger.warning('NOTIFICATIONS_REFRESH_TIME setting is invalid. Using default.')
|
logger.warning('NOTIFICATIONS_REFRESH_TIME setting is invalid. Using default.')
|
||||||
|
|||||||
@ -13,16 +13,16 @@ class TestUserNotificationCount(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user = AuthUtils.create_user('magic_mike')
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user,
|
cls.user,
|
||||||
'Magic Mike',
|
'Magic Mike',
|
||||||
'1',
|
'1',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_notify(self):
|
def test_can_notify(self):
|
||||||
notify(self.user, 'dummy')
|
notify(self.user, 'dummy')
|
||||||
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
||||||
|
|||||||
@ -18,14 +18,14 @@ class TestQuerySet(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user_1 = AuthUtils.create_user('Peter Parker')
|
cls.user_1 = AuthUtils.create_user('Peter Parker')
|
||||||
cls.user_2 = AuthUtils.create_user('Clark Kent')
|
cls.user_2 = AuthUtils.create_user('Clark Kent')
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
||||||
def test_update_will_invalidate_cache(
|
def test_update_will_invalidate_cache(
|
||||||
self, mock_invalidate_user_notification_cache
|
self, mock_invalidate_user_notification_cache
|
||||||
):
|
):
|
||||||
Notification.objects.notify_user(self.user_1, 'dummy_1')
|
Notification.objects.notify_user(self.user_1, 'dummy_1')
|
||||||
Notification.objects.notify_user(self.user_2, 'dummy_2')
|
Notification.objects.notify_user(self.user_2, 'dummy_2')
|
||||||
Notification.objects.update(viewed=True)
|
Notification.objects.update(viewed=True)
|
||||||
self.assertEquals(mock_invalidate_user_notification_cache.call_count, 2)
|
self.assertEquals(mock_invalidate_user_notification_cache.call_count, 2)
|
||||||
|
|
||||||
|
|
||||||
@ -34,16 +34,16 @@ class TestUserNotify(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user = AuthUtils.create_user('magic_mike')
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user,
|
cls.user,
|
||||||
'Magic Mike',
|
'Magic Mike',
|
||||||
'1',
|
'1',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_notify(self):
|
def test_can_notify(self):
|
||||||
title = 'dummy_title'
|
title = 'dummy_title'
|
||||||
message = 'dummy message'
|
message = 'dummy message'
|
||||||
@ -57,14 +57,14 @@ class TestUserNotify(TestCase):
|
|||||||
self.assertEqual(obj.level, level)
|
self.assertEqual(obj.level, level)
|
||||||
|
|
||||||
def test_use_message_as_title_if_missing(self):
|
def test_use_message_as_title_if_missing(self):
|
||||||
title = 'dummy_title'
|
title = 'dummy_title'
|
||||||
Notification.objects.notify_user(self.user, title)
|
Notification.objects.notify_user(self.user, title)
|
||||||
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
||||||
obj = Notification.objects.first()
|
obj = Notification.objects.first()
|
||||||
self.assertEqual(obj.user, self.user)
|
self.assertEqual(obj.user, self.user)
|
||||||
self.assertEqual(obj.title, title)
|
self.assertEqual(obj.title, title)
|
||||||
self.assertEqual(obj.message, title)
|
self.assertEqual(obj.message, title)
|
||||||
|
|
||||||
@override_settings(NOTIFICATIONS_MAX_PER_USER=3)
|
@override_settings(NOTIFICATIONS_MAX_PER_USER=3)
|
||||||
def test_remove_when_too_many_notifications(self):
|
def test_remove_when_too_many_notifications(self):
|
||||||
Notification.objects.notify_user(self.user, 'dummy')
|
Notification.objects.notify_user(self.user, 'dummy')
|
||||||
@ -116,16 +116,16 @@ class TestUnreadCount(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user_1 = AuthUtils.create_user('magic_mike')
|
cls.user_1 = AuthUtils.create_user('magic_mike')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user_1,
|
cls.user_1,
|
||||||
'Magic Mike',
|
'Magic Mike',
|
||||||
'1',
|
'1',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
|
|
||||||
# test notifications for mike
|
# test notifications for mike
|
||||||
Notification.objects.all().delete()
|
Notification.objects.all().delete()
|
||||||
Notification.objects.create(
|
Notification.objects.create(
|
||||||
@ -146,19 +146,19 @@ class TestUnreadCount(TestCase):
|
|||||||
level="INFO",
|
level="INFO",
|
||||||
title="Job 3 Failed",
|
title="Job 3 Failed",
|
||||||
message="Because it was broken"
|
message="Because it was broken"
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.user_2 = AuthUtils.create_user('teh_kid')
|
cls.user_2 = AuthUtils.create_user('teh_kid')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user_2,
|
cls.user_2,
|
||||||
'The Kid', '2',
|
'The Kid', '2',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Notifications for kid
|
# Notifications for kid
|
||||||
Notification.objects.create(
|
Notification.objects.create(
|
||||||
user=cls.user_2,
|
user=cls.user_2,
|
||||||
@ -166,7 +166,7 @@ class TestUnreadCount(TestCase):
|
|||||||
title="Job 6 Failed",
|
title="Job 6 Failed",
|
||||||
message="Because it was broken"
|
message="Because it was broken"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_update_cache_when_not_in_cache(self, mock_cache):
|
def test_update_cache_when_not_in_cache(self, mock_cache):
|
||||||
mock_cache.get.return_value = None
|
mock_cache.get.return_value = None
|
||||||
|
|
||||||
@ -174,9 +174,9 @@ class TestUnreadCount(TestCase):
|
|||||||
expected = 2
|
expected = 2
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
self.assertTrue(mock_cache.set.called)
|
self.assertTrue(mock_cache.set.called)
|
||||||
args, kwargs = mock_cache.set.call_args
|
args, kwargs = mock_cache.set.call_args
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
kwargs['key'],
|
kwargs['key'],
|
||||||
Notification.objects._user_notification_cache_key(self.user_1.pk)
|
Notification.objects._user_notification_cache_key(self.user_1.pk)
|
||||||
)
|
)
|
||||||
self.assertEqual(kwargs['value'], expected)
|
self.assertEqual(kwargs['value'], expected)
|
||||||
@ -195,12 +195,12 @@ class TestUnreadCount(TestCase):
|
|||||||
expected = -1
|
expected = -1
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
self.assertFalse(mock_cache.set.called)
|
self.assertFalse(mock_cache.set.called)
|
||||||
|
|
||||||
def test_can_invalidate_cache(self, mock_cache):
|
def test_can_invalidate_cache(self, mock_cache):
|
||||||
Notification.objects.invalidate_user_notification_cache(self.user_1.pk)
|
Notification.objects.invalidate_user_notification_cache(self.user_1.pk)
|
||||||
self.assertTrue(mock_cache.delete)
|
self.assertTrue(mock_cache.delete)
|
||||||
args, kwargs = mock_cache.delete.call_args
|
args, kwargs = mock_cache.delete.call_args
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
kwargs['key'],
|
kwargs['key'],
|
||||||
Notification.objects._user_notification_cache_key(self.user_1.pk)
|
Notification.objects._user_notification_cache_key(self.user_1.pk)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -15,16 +15,16 @@ class TestUserNotify(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user = AuthUtils.create_user('magic_mike')
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user,
|
cls.user,
|
||||||
'Magic Mike',
|
'Magic Mike',
|
||||||
'1',
|
'1',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
||||||
def test_save_will_invalidate_cache(self, mock_invalidate_user_notification_cache):
|
def test_save_will_invalidate_cache(self, mock_invalidate_user_notification_cache):
|
||||||
obj = Notification.objects.notify_user(self.user, 'dummy')
|
obj = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
|||||||
@ -20,20 +20,20 @@ class TestUserNotificationCount(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user = AuthUtils.create_user('magic_mike')
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user,
|
cls.user,
|
||||||
'Magic Mike',
|
'Magic Mike',
|
||||||
'1',
|
'1',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_return_normal(self, mock_user_unread_count):
|
def test_return_normal(self, mock_user_unread_count):
|
||||||
unread_count = 42
|
unread_count = 42
|
||||||
mock_user_unread_count.return_value = unread_count
|
mock_user_unread_count.return_value = unread_count
|
||||||
|
|
||||||
result = user_unread_notification_count(self.user)
|
result = user_unread_notification_count(self.user)
|
||||||
expected = unread_count
|
expected = unread_count
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
@ -43,7 +43,7 @@ class TestUserNotificationCount(TestCase):
|
|||||||
def test_return_error_if_non_user(self, mock_user_unread_count):
|
def test_return_error_if_non_user(self, mock_user_unread_count):
|
||||||
unread_count = -1
|
unread_count = -1
|
||||||
mock_user_unread_count.return_value = unread_count
|
mock_user_unread_count.return_value = unread_count
|
||||||
|
|
||||||
result = user_unread_notification_count('invalid')
|
result = user_unread_notification_count('invalid')
|
||||||
expected = unread_count
|
expected = unread_count
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
@ -60,9 +60,9 @@ class TestNotificationsRefreshTime(TestCase):
|
|||||||
result = notifications_refresh_time()
|
result = notifications_refresh_time()
|
||||||
expected = MY_NOTIFICATIONS_REFRESH_TIME
|
expected = MY_NOTIFICATIONS_REFRESH_TIME
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
@override_settings(NOTIFICATIONS_REFRESH_TIME=0)
|
@override_settings(NOTIFICATIONS_REFRESH_TIME=0)
|
||||||
def test_refresh_time_can_be_zero(self):
|
def test_refresh_time_can_be_zero(self):
|
||||||
result = notifications_refresh_time()
|
result = notifications_refresh_time()
|
||||||
expected = 0
|
expected = 0
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|||||||
@ -19,23 +19,23 @@ class TestViews(TestCase):
|
|||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user = AuthUtils.create_user('magic_mike')
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
cls.user,
|
cls.user,
|
||||||
'Magic Mike',
|
'Magic Mike',
|
||||||
'1',
|
'1',
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='Pole Riders',
|
corp_name='Pole Riders',
|
||||||
corp_ticker='PRIDE',
|
corp_ticker='PRIDE',
|
||||||
alliance_id='3',
|
alliance_id='3',
|
||||||
alliance_name='RIDERS'
|
alliance_name='RIDERS'
|
||||||
)
|
)
|
||||||
cls.factory = RequestFactory()
|
cls.factory = RequestFactory()
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.Notification.objects.user_unread_count')
|
@patch(MODULE_PATH + '.Notification.objects.user_unread_count')
|
||||||
def test_user_notifications_count(self, mock_user_unread_count):
|
def test_user_notifications_count(self, mock_user_unread_count):
|
||||||
unread_count = 42
|
unread_count = 42
|
||||||
user_pk = 3
|
user_pk = 3
|
||||||
mock_user_unread_count.return_value = unread_count
|
mock_user_unread_count.return_value = unread_count
|
||||||
|
|
||||||
request = self.factory.get(
|
request = self.factory.get(
|
||||||
reverse('notifications:user_notifications_count', args=[user_pk])
|
reverse('notifications:user_notifications_count', args=[user_pk])
|
||||||
)
|
)
|
||||||
@ -43,7 +43,7 @@ class TestViews(TestCase):
|
|||||||
|
|
||||||
response = user_notifications_count(request, user_pk)
|
response = user_notifications_count(request, user_pk)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue(mock_user_unread_count.called)
|
self.assertTrue(mock_user_unread_count.called)
|
||||||
expected = {'unread_count': unread_count}
|
expected = {'unread_count': unread_count}
|
||||||
result = json.loads(response.content.decode(response.charset))
|
result = json.loads(response.content.decode(response.charset))
|
||||||
self.assertDictEqual(result, expected)
|
self.assertDictEqual(result, expected)
|
||||||
|
|||||||
@ -10,8 +10,8 @@ urlpatterns = [
|
|||||||
url(r'^notifications/$', views.notification_list, name='list'),
|
url(r'^notifications/$', views.notification_list, name='list'),
|
||||||
url(r'^notifications/(\w+)/$', views.notification_view, name='view'),
|
url(r'^notifications/(\w+)/$', views.notification_view, name='view'),
|
||||||
url(
|
url(
|
||||||
r'^user_notifications_count/(?P<user_pk>\d+)/$',
|
r'^user_notifications_count/(?P<user_pk>\d+)/$',
|
||||||
views.user_notifications_count,
|
views.user_notifications_count,
|
||||||
name='user_notifications_count'
|
name='user_notifications_count'
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -18,9 +18,9 @@ def notification_list(request):
|
|||||||
new_notifs = notifications_qs.filter(viewed=False)
|
new_notifs = notifications_qs.filter(viewed=False)
|
||||||
old_notifs = notifications_qs.filter(viewed=True)
|
old_notifs = notifications_qs.filter(viewed=True)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"User %s has %s unread and %s read notifications",
|
"User %s has %s unread and %s read notifications",
|
||||||
request.user,
|
request.user,
|
||||||
len(new_notifs),
|
len(new_notifs),
|
||||||
len(old_notifs)
|
len(old_notifs)
|
||||||
)
|
)
|
||||||
context = {
|
context = {
|
||||||
@ -33,8 +33,8 @@ def notification_list(request):
|
|||||||
@login_required
|
@login_required
|
||||||
def notification_view(request, notif_id):
|
def notification_view(request, notif_id):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"notification_view called by user %s for notif_id %s",
|
"notification_view called by user %s for notif_id %s",
|
||||||
request.user,
|
request.user,
|
||||||
notif_id
|
notif_id
|
||||||
)
|
)
|
||||||
notif = get_object_or_404(Notification, pk=notif_id)
|
notif = get_object_or_404(Notification, pk=notif_id)
|
||||||
@ -46,7 +46,7 @@ def notification_view(request, notif_id):
|
|||||||
else:
|
else:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"User %s not authorized to view notif_id %s belonging to user %s",
|
"User %s not authorized to view notif_id %s belonging to user %s",
|
||||||
request.user,
|
request.user,
|
||||||
notif_id, notif.user
|
notif_id, notif.user
|
||||||
)
|
)
|
||||||
messages.error(request, _('You are not authorized to view that notification.'))
|
messages.error(request, _('You are not authorized to view that notification.'))
|
||||||
@ -57,7 +57,7 @@ def notification_view(request, notif_id):
|
|||||||
def remove_notification(request, notif_id):
|
def remove_notification(request, notif_id):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"remove notification called by user %s for notif_id %s",
|
"remove notification called by user %s for notif_id %s",
|
||||||
request.user,
|
request.user,
|
||||||
notif_id
|
notif_id
|
||||||
)
|
)
|
||||||
notif = get_object_or_404(Notification, pk=notif_id)
|
notif = get_object_or_404(Notification, pk=notif_id)
|
||||||
@ -68,8 +68,8 @@ def remove_notification(request, notif_id):
|
|||||||
messages.success(request, _('Deleted notification.'))
|
messages.success(request, _('Deleted notification.'))
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Unable to delete notif id %s for user %s - notif matching id not found.",
|
"Unable to delete notif id %s for user %s - notif matching id not found.",
|
||||||
notif_id,
|
notif_id,
|
||||||
request.user
|
request.user
|
||||||
)
|
)
|
||||||
messages.error(request, _('Failed to locate notification.'))
|
messages.error(request, _('Failed to locate notification.'))
|
||||||
@ -94,9 +94,9 @@ def delete_all_read(request):
|
|||||||
|
|
||||||
def user_notifications_count(request, user_pk: int):
|
def user_notifications_count(request, user_pk: int):
|
||||||
"""returns to notifications count for the give user as JSON
|
"""returns to notifications count for the give user as JSON
|
||||||
|
|
||||||
This view is public and does not require login
|
This view is public and does not require login
|
||||||
"""
|
"""
|
||||||
unread_count = Notification.objects.user_unread_count(user_pk)
|
unread_count = Notification.objects.user_unread_count(user_pk)
|
||||||
data = {'unread_count': unread_count}
|
data = {'unread_count': unread_count}
|
||||||
return JsonResponse(data, safe=False)
|
return JsonResponse(data, safe=False)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{% load evelinks %}
|
{% load evelinks %}
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{{ type }}: {{ name }}
|
{{ type }}: {{ name }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
@ -20,6 +20,6 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
(unknown)
|
(unknown)
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -104,7 +104,7 @@ TEMPLATES = [
|
|||||||
'django.template.context_processors.i18n',
|
'django.template.context_processors.i18n',
|
||||||
'django.template.context_processors.media',
|
'django.template.context_processors.media',
|
||||||
'django.template.context_processors.static',
|
'django.template.context_processors.static',
|
||||||
'django.template.context_processors.tz',
|
'django.template.context_processors.tz',
|
||||||
'allianceauth.context_processors.auth_settings',
|
'allianceauth.context_processors.auth_settings',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -19,7 +19,7 @@ DEBUG = False
|
|||||||
|
|
||||||
# Add any additional apps to this list.
|
# Add any additional apps to this list.
|
||||||
INSTALLED_APPS += [
|
INSTALLED_APPS += [
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# To change the logging level for extensions, uncomment the following line.
|
# To change the logging level for extensions, uncomment the following line.
|
||||||
|
|||||||
@ -3,9 +3,9 @@ from django.contrib import admin
|
|||||||
|
|
||||||
from allianceauth import hooks
|
from allianceauth import hooks
|
||||||
from allianceauth.authentication.admin import (
|
from allianceauth.authentication.admin import (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
user_main_organization,
|
user_main_organization,
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter
|
MainAllianceFilter
|
||||||
)
|
)
|
||||||
@ -22,17 +22,17 @@ class ServicesUserAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
search_fields = ('user__username',)
|
search_fields = ('user__username',)
|
||||||
ordering = ('user__username',)
|
ordering = ('user__username',)
|
||||||
list_select_related = True
|
list_select_related = True
|
||||||
list_display = (
|
list_display = (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
'_state',
|
'_state',
|
||||||
user_main_organization,
|
user_main_organization,
|
||||||
'_date_joined'
|
'_date_joined'
|
||||||
)
|
)
|
||||||
list_filter = (
|
list_filter = (
|
||||||
'user__profile__state',
|
'user__profile__state',
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
'user__date_joined',
|
'user__date_joined',
|
||||||
)
|
)
|
||||||
@ -45,7 +45,7 @@ class ServicesUserAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
def _date_joined(self, obj):
|
def _date_joined(self, obj):
|
||||||
return obj.user.date_joined
|
return obj.user.date_joined
|
||||||
|
|
||||||
_date_joined.short_description = 'date joined'
|
_date_joined.short_description = 'date joined'
|
||||||
_date_joined.admin_order_field = 'user__date_joined'
|
_date_joined.admin_order_field = 'user__date_joined'
|
||||||
|
|
||||||
|
|||||||
@ -139,11 +139,11 @@ class MenuItemHook:
|
|||||||
self.url_name = url_name
|
self.url_name = url_name
|
||||||
self.template = 'public/menuitem.html'
|
self.template = 'public/menuitem.html'
|
||||||
self.order = order if order is not None else 9999
|
self.order = order if order is not None else 9999
|
||||||
|
|
||||||
# count is an integer shown next to the menu item as badge when count != None
|
# count is an integer shown next to the menu item as badge when count != None
|
||||||
# apps need to set the count in their child class, e.g. in render() method
|
# apps need to set the count in their child class, e.g. in render() method
|
||||||
self.count = None
|
self.count = None
|
||||||
|
|
||||||
navactive = navactive or []
|
navactive = navactive or []
|
||||||
navactive.append(url_name)
|
navactive.append(url_name)
|
||||||
self.navactive = navactive
|
self.navactive = navactive
|
||||||
|
|||||||
@ -6,7 +6,7 @@ from allianceauth.authentication.models import State
|
|||||||
class NameFormatConfig(models.Model):
|
class NameFormatConfig(models.Model):
|
||||||
service_name = models.CharField(max_length=100, blank=False)
|
service_name = models.CharField(max_length=100, blank=False)
|
||||||
default_to_username = models.BooleanField(
|
default_to_username = models.BooleanField(
|
||||||
default=True,
|
default=True,
|
||||||
help_text=
|
help_text=
|
||||||
'If a user has no main_character, '
|
'If a user has no main_character, '
|
||||||
'default to using their Auth username instead.'
|
'default to using their Auth username instead.'
|
||||||
@ -20,10 +20,10 @@ class NameFormatConfig(models.Model):
|
|||||||
'topic "Services Name Formats".'
|
'topic "Services Name Formats".'
|
||||||
)
|
)
|
||||||
states = models.ManyToManyField(
|
states = models.ManyToManyField(
|
||||||
State,
|
State,
|
||||||
help_text=
|
help_text=
|
||||||
"States to apply this format to. You should only have one "
|
"States to apply this format to. You should only have one "
|
||||||
"formatter for each state for each service."
|
"formatter for each state for each service."
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@ -12,15 +12,15 @@ logger = LoggerAddTag(logging.getLogger(__name__), __title__)
|
|||||||
|
|
||||||
|
|
||||||
@admin.register(DiscordUser)
|
@admin.register(DiscordUser)
|
||||||
class DiscordUserAdmin(ServicesUserAdmin):
|
class DiscordUserAdmin(ServicesUserAdmin):
|
||||||
search_fields = ServicesUserAdmin.search_fields + ('uid', 'username')
|
search_fields = ServicesUserAdmin.search_fields + ('uid', 'username')
|
||||||
list_display = ServicesUserAdmin.list_display + ('activated', '_username', '_uid')
|
list_display = ServicesUserAdmin.list_display + ('activated', '_username', '_uid')
|
||||||
list_filter = ServicesUserAdmin.list_filter + ('activated',)
|
list_filter = ServicesUserAdmin.list_filter + ('activated',)
|
||||||
ordering = ('-activated',)
|
ordering = ('-activated',)
|
||||||
|
|
||||||
def _uid(self, obj):
|
def _uid(self, obj):
|
||||||
return obj.uid
|
return obj.uid
|
||||||
|
|
||||||
_uid.short_description = 'Discord ID (UID)'
|
_uid.short_description = 'Discord ID (UID)'
|
||||||
_uid.admin_order_field = 'uid'
|
_uid.admin_order_field = 'uid'
|
||||||
|
|
||||||
@ -29,6 +29,6 @@ class DiscordUserAdmin(ServicesUserAdmin):
|
|||||||
return f'{obj.username}#{obj.discriminator}'
|
return f'{obj.username}#{obj.discriminator}'
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
_username.short_description = 'Discord Username'
|
_username.short_description = 'Discord Username'
|
||||||
_username.admin_order_field = 'username'
|
_username.admin_order_field = 'username'
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
|
||||||
from allianceauth import hooks
|
from allianceauth import hooks
|
||||||
@ -33,11 +33,11 @@ class DiscordService(ServicesHook):
|
|||||||
if self.user_has_account(user):
|
if self.user_has_account(user):
|
||||||
logger.debug('Deleting user %s %s account', user, self.name)
|
logger.debug('Deleting user %s %s account', user, self.name)
|
||||||
tasks.delete_user.apply_async(
|
tasks.delete_user.apply_async(
|
||||||
kwargs={'user_pk': user.pk, 'notify_user': notify_user},
|
kwargs={'user_pk': user.pk, 'notify_user': notify_user},
|
||||||
priority=SINGLE_TASK_PRIORITY
|
priority=SINGLE_TASK_PRIORITY
|
||||||
)
|
)
|
||||||
|
|
||||||
def render_services_ctrl(self, request):
|
def render_services_ctrl(self, request):
|
||||||
if self.user_has_account(request.user):
|
if self.user_has_account(request.user):
|
||||||
user_has_account = True
|
user_has_account = True
|
||||||
username = request.user.discord.username
|
username = request.user.discord.username
|
||||||
@ -51,12 +51,12 @@ class DiscordService(ServicesHook):
|
|||||||
user_has_account = False
|
user_has_account = False
|
||||||
|
|
||||||
return render_to_string(
|
return render_to_string(
|
||||||
self.service_ctrl_template,
|
self.service_ctrl_template,
|
||||||
{
|
{
|
||||||
'server_name': DiscordUser.objects.server_name(),
|
'server_name': DiscordUser.objects.server_name(),
|
||||||
'user_has_account': user_has_account,
|
'user_has_account': user_has_account,
|
||||||
'discord_username': discord_username
|
'discord_username': discord_username
|
||||||
},
|
},
|
||||||
request=request
|
request=request
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -71,15 +71,15 @@ class DiscordService(ServicesHook):
|
|||||||
tasks.update_nickname.apply_async(
|
tasks.update_nickname.apply_async(
|
||||||
kwargs={
|
kwargs={
|
||||||
'user_pk': user.pk,
|
'user_pk': user.pk,
|
||||||
# since the new nickname is not yet in the DB we need to
|
# since the new nickname is not yet in the DB we need to
|
||||||
# provide it manually to the task
|
# provide it manually to the task
|
||||||
'nickname': DiscordUser.objects.user_formatted_nick(user)
|
'nickname': DiscordUser.objects.user_formatted_nick(user)
|
||||||
},
|
},
|
||||||
priority=SINGLE_TASK_PRIORITY
|
priority=SINGLE_TASK_PRIORITY
|
||||||
)
|
)
|
||||||
|
|
||||||
def sync_nicknames_bulk(self, users: list):
|
def sync_nicknames_bulk(self, users: list):
|
||||||
"""Sync nickname for a list of users in bulk.
|
"""Sync nickname for a list of users in bulk.
|
||||||
Preferred over sync_nickname(), because it will not break the rate limit
|
Preferred over sync_nickname(), because it will not break the rate limit
|
||||||
"""
|
"""
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@ -92,21 +92,21 @@ class DiscordService(ServicesHook):
|
|||||||
logger.debug('Update all %s groups called', self.name)
|
logger.debug('Update all %s groups called', self.name)
|
||||||
tasks.update_all_groups.delay()
|
tasks.update_all_groups.delay()
|
||||||
|
|
||||||
def update_groups(self, user):
|
def update_groups(self, user):
|
||||||
logger.debug('Processing %s groups for %s', self.name, user)
|
logger.debug('Processing %s groups for %s', self.name, user)
|
||||||
if self.user_has_account(user):
|
if self.user_has_account(user):
|
||||||
tasks.update_groups.apply_async(
|
tasks.update_groups.apply_async(
|
||||||
kwargs={
|
kwargs={
|
||||||
'user_pk': user.pk,
|
'user_pk': user.pk,
|
||||||
# since state changes may not yet be in the DB we need to
|
# since state changes may not yet be in the DB we need to
|
||||||
# provide the new state name manually to the task
|
# provide the new state name manually to the task
|
||||||
'state_name': user.profile.state.name
|
'state_name': user.profile.state.name
|
||||||
},
|
},
|
||||||
priority=SINGLE_TASK_PRIORITY
|
priority=SINGLE_TASK_PRIORITY
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_groups_bulk(self, users: list):
|
def update_groups_bulk(self, users: list):
|
||||||
"""Updates groups for a list of users in bulk.
|
"""Updates groups for a list of users in bulk.
|
||||||
Preferred over update_groups(), because it will not break the rate limit
|
Preferred over update_groups(), because it will not break the rate limit
|
||||||
"""
|
"""
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@ -114,7 +114,7 @@ class DiscordService(ServicesHook):
|
|||||||
)
|
)
|
||||||
user_pks = [user.pk for user in users]
|
user_pks = [user.pk for user in users]
|
||||||
tasks.update_groups_bulk.delay(user_pks)
|
tasks.update_groups_bulk.delay(user_pks)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def user_has_account(user: User) -> bool:
|
def user_has_account(user: User) -> bool:
|
||||||
result = DiscordUser.objects.user_has_account(user)
|
result = DiscordUser.objects.user_has_account(user)
|
||||||
|
|||||||
@ -26,7 +26,7 @@ DISCORD_OAUTH_TOKEN_URL = clean_setting(
|
|||||||
'DISCORD_OAUTH_TOKEN_URL', 'https://discord.com/api/oauth2/token'
|
'DISCORD_OAUTH_TOKEN_URL', 'https://discord.com/api/oauth2/token'
|
||||||
)
|
)
|
||||||
|
|
||||||
# How long the Discord guild names retrieved from the server are
|
# How long the Discord guild names retrieved from the server are
|
||||||
# caches locally in seconds.
|
# caches locally in seconds.
|
||||||
DISCORD_GUILD_NAME_CACHE_MAX_AGE = clean_setting(
|
DISCORD_GUILD_NAME_CACHE_MAX_AGE = clean_setting(
|
||||||
'DISCORD_GUILD_NAME_CACHE_MAX_AGE', 3600 * 24
|
'DISCORD_GUILD_NAME_CACHE_MAX_AGE', 3600 * 24
|
||||||
@ -38,7 +38,7 @@ DISCORD_ROLES_CACHE_MAX_AGE = clean_setting(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Turns off creation of new roles. In case the rate limit for creating roles is
|
# Turns off creation of new roles. In case the rate limit for creating roles is
|
||||||
# exhausted, this setting allows the Discord service to continue to function
|
# exhausted, this setting allows the Discord service to continue to function
|
||||||
# and wait out the reset. Rate limit is about 250 per 48 hrs.
|
# and wait out the reset. Rate limit is about 250 per 48 hrs.
|
||||||
DISCORD_DISABLE_ROLE_CREATION = clean_setting(
|
DISCORD_DISABLE_ROLE_CREATION = clean_setting(
|
||||||
'DISCORD_DISABLE_ROLE_CREATION', False
|
'DISCORD_DISABLE_ROLE_CREATION', False
|
||||||
|
|||||||
@ -19,9 +19,9 @@ from .app_settings import (
|
|||||||
DISCORD_API_TIMEOUT_READ,
|
DISCORD_API_TIMEOUT_READ,
|
||||||
DISCORD_DISABLE_ROLE_CREATION,
|
DISCORD_DISABLE_ROLE_CREATION,
|
||||||
DISCORD_GUILD_NAME_CACHE_MAX_AGE,
|
DISCORD_GUILD_NAME_CACHE_MAX_AGE,
|
||||||
DISCORD_OAUTH_BASE_URL,
|
DISCORD_OAUTH_BASE_URL,
|
||||||
DISCORD_OAUTH_TOKEN_URL,
|
DISCORD_OAUTH_TOKEN_URL,
|
||||||
DISCORD_ROLES_CACHE_MAX_AGE,
|
DISCORD_ROLES_CACHE_MAX_AGE,
|
||||||
)
|
)
|
||||||
from .exceptions import DiscordRateLimitExhausted, DiscordTooManyRequestsError
|
from .exceptions import DiscordRateLimitExhausted, DiscordTooManyRequestsError
|
||||||
from .helpers import DiscordRoles
|
from .helpers import DiscordRoles
|
||||||
@ -31,7 +31,7 @@ from ..utils import LoggerAddTag
|
|||||||
logger = LoggerAddTag(logging.getLogger(__name__), __title__)
|
logger = LoggerAddTag(logging.getLogger(__name__), __title__)
|
||||||
|
|
||||||
# max requests that can be executed until reset
|
# max requests that can be executed until reset
|
||||||
RATE_LIMIT_MAX_REQUESTS = 5
|
RATE_LIMIT_MAX_REQUESTS = 5
|
||||||
|
|
||||||
# Time until remaining requests are reset
|
# Time until remaining requests are reset
|
||||||
RATE_LIMIT_RESETS_AFTER = 5000
|
RATE_LIMIT_RESETS_AFTER = 5000
|
||||||
@ -39,7 +39,7 @@ RATE_LIMIT_RESETS_AFTER = 5000
|
|||||||
# Delay used for API backoff in case no info returned from API on 429s
|
# Delay used for API backoff in case no info returned from API on 429s
|
||||||
DEFAULT_BACKOFF_DELAY = 5000
|
DEFAULT_BACKOFF_DELAY = 5000
|
||||||
|
|
||||||
# additional duration to compensate for potential clock discrepancies
|
# additional duration to compensate for potential clock discrepancies
|
||||||
# with the Discord server
|
# with the Discord server
|
||||||
DURATION_CONTINGENCY = 500
|
DURATION_CONTINGENCY = 500
|
||||||
|
|
||||||
@ -51,23 +51,23 @@ WAIT_THRESHOLD = 250
|
|||||||
MINIMUM_BLOCKING_WAIT = 50
|
MINIMUM_BLOCKING_WAIT = 50
|
||||||
|
|
||||||
# If the rate limit resets soon we will wait it out and then retry to
|
# If the rate limit resets soon we will wait it out and then retry to
|
||||||
# either get a remaining request from our cached counter
|
# either get a remaining request from our cached counter
|
||||||
# or again wait out a short reset time and retry again.
|
# or again wait out a short reset time and retry again.
|
||||||
# This could happen several times within a high concurrency situation,
|
# This could happen several times within a high concurrency situation,
|
||||||
# but must fail after x tries to avoid an infinite loop
|
# but must fail after x tries to avoid an infinite loop
|
||||||
RATE_LIMIT_RETRIES = 1000
|
RATE_LIMIT_RETRIES = 1000
|
||||||
|
|
||||||
|
|
||||||
class DiscordClient:
|
class DiscordClient:
|
||||||
"""This class provides a web client for interacting with the Discord API
|
"""This class provides a web client for interacting with the Discord API
|
||||||
|
|
||||||
The client has rate limiting that supports concurrency.
|
The client has rate limiting that supports concurrency.
|
||||||
This means it is able to ensure the API rate limit is not violated,
|
This means it is able to ensure the API rate limit is not violated,
|
||||||
even when used concurrently, e.g. with multiple parallel celery tasks.
|
even when used concurrently, e.g. with multiple parallel celery tasks.
|
||||||
|
|
||||||
In addition the client support proper API backoff.
|
In addition the client support proper API backoff.
|
||||||
|
|
||||||
Synchronization of rate limit infos accross multiple processes
|
Synchronization of rate limit infos accross multiple processes
|
||||||
is implemented with Redis and thus requires Redis as Django cache backend.
|
is implemented with Redis and thus requires Redis as Django cache backend.
|
||||||
|
|
||||||
All durations are in milliseconds.
|
All durations are in milliseconds.
|
||||||
@ -79,25 +79,25 @@ class DiscordClient:
|
|||||||
_KEY_GLOBAL_RATE_LIMIT_REMAINING = 'DISCORD_GLOBAL_RATE_LIMIT_REMAINING'
|
_KEY_GLOBAL_RATE_LIMIT_REMAINING = 'DISCORD_GLOBAL_RATE_LIMIT_REMAINING'
|
||||||
_KEYPREFIX_GUILD_NAME = 'DISCORD_GUILD_NAME'
|
_KEYPREFIX_GUILD_NAME = 'DISCORD_GUILD_NAME'
|
||||||
_KEYPREFIX_GUILD_ROLES = 'DISCORD_GUILD_ROLES'
|
_KEYPREFIX_GUILD_ROLES = 'DISCORD_GUILD_ROLES'
|
||||||
_KEYPREFIX_ROLE_NAME = 'DISCORD_ROLE_NAME'
|
_KEYPREFIX_ROLE_NAME = 'DISCORD_ROLE_NAME'
|
||||||
_NICK_MAX_CHARS = 32
|
_NICK_MAX_CHARS = 32
|
||||||
|
|
||||||
_HTTP_STATUS_CODE_NOT_FOUND = 404
|
_HTTP_STATUS_CODE_NOT_FOUND = 404
|
||||||
_HTTP_STATUS_CODE_RATE_LIMITED = 429
|
_HTTP_STATUS_CODE_RATE_LIMITED = 429
|
||||||
_DISCORD_STATUS_CODE_UNKNOWN_MEMBER = 10007
|
_DISCORD_STATUS_CODE_UNKNOWN_MEMBER = 10007
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
access_token: str,
|
access_token: str,
|
||||||
redis: Redis = None,
|
redis: Redis = None,
|
||||||
is_rate_limited: bool = True
|
is_rate_limited: bool = True
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Params:
|
Params:
|
||||||
- access_token: Discord access token used to authenticate all calls to the API
|
- access_token: Discord access token used to authenticate all calls to the API
|
||||||
- redis: Redis instance to be used.
|
- redis: Redis instance to be used.
|
||||||
- is_rate_limited: Set to False to run of rate limiting (use with care)
|
- is_rate_limited: Set to False to run of rate limiting (use with care)
|
||||||
If not specified will try to use the Redis instance
|
If not specified will try to use the Redis instance
|
||||||
from the default Django cache backend.
|
from the default Django cache backend.
|
||||||
"""
|
"""
|
||||||
self._access_token = str(access_token)
|
self._access_token = str(access_token)
|
||||||
@ -116,7 +116,7 @@ class DiscordClient:
|
|||||||
lua_1 = """
|
lua_1 = """
|
||||||
if redis.call("exists", KEYS[1]) == 0 then
|
if redis.call("exists", KEYS[1]) == 0 then
|
||||||
redis.call("set", KEYS[1], ARGV[1], 'px', ARGV[2])
|
redis.call("set", KEYS[1], ARGV[1], 'px', ARGV[2])
|
||||||
end
|
end
|
||||||
return redis.call("decr", KEYS[1])
|
return redis.call("decr", KEYS[1])
|
||||||
"""
|
"""
|
||||||
self.__redis_script_decr_or_set = self._redis.register_script(lua_1)
|
self.__redis_script_decr_or_set = self._redis.register_script(lua_1)
|
||||||
@ -138,24 +138,24 @@ class DiscordClient:
|
|||||||
@property
|
@property
|
||||||
def is_rate_limited(self):
|
def is_rate_limited(self):
|
||||||
return self._is_rate_limited
|
return self._is_rate_limited
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{type(self).__name__}(access_token=...{self.access_token[-5:]})'
|
return f'{type(self).__name__}(access_token=...{self.access_token[-5:]})'
|
||||||
|
|
||||||
def _redis_decr_or_set(self, name: str, value: str, px: int) -> bool:
|
def _redis_decr_or_set(self, name: str, value: str, px: int) -> bool:
|
||||||
"""decreases the key value if it exists and returns the result
|
"""decreases the key value if it exists and returns the result
|
||||||
else sets the key
|
else sets the key
|
||||||
|
|
||||||
Implemented as Lua script to ensure atomicity.
|
Implemented as Lua script to ensure atomicity.
|
||||||
"""
|
"""
|
||||||
return self.__redis_script_decr_or_set(
|
return self.__redis_script_decr_or_set(
|
||||||
keys=[str(name)], args=[str(value), int(px)]
|
keys=[str(name)], args=[str(value), int(px)]
|
||||||
)
|
)
|
||||||
|
|
||||||
def _redis_set_if_longer(self, name: str, value: str, px: int) -> bool:
|
def _redis_set_if_longer(self, name: str, value: str, px: int) -> bool:
|
||||||
"""like set, but only goes through if either key doesn't exist
|
"""like set, but only goes through if either key doesn't exist
|
||||||
or px would be extended.
|
or px would be extended.
|
||||||
|
|
||||||
Implemented as Lua script to ensure atomicity.
|
Implemented as Lua script to ensure atomicity.
|
||||||
"""
|
"""
|
||||||
return self.__redis_script_set_longer(
|
return self.__redis_script_set_longer(
|
||||||
@ -163,7 +163,7 @@ class DiscordClient:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# users
|
# users
|
||||||
|
|
||||||
def current_user(self) -> dict:
|
def current_user(self) -> dict:
|
||||||
"""returns the user belonging to the current access_token"""
|
"""returns the user belonging to the current access_token"""
|
||||||
authorization = f'Bearer {self.access_token}'
|
authorization = f'Bearer {self.access_token}'
|
||||||
@ -171,7 +171,7 @@ class DiscordClient:
|
|||||||
method='get', route='users/@me', authorization=authorization
|
method='get', route='users/@me', authorization=authorization
|
||||||
)
|
)
|
||||||
return r.json()
|
return r.json()
|
||||||
|
|
||||||
# guild
|
# guild
|
||||||
|
|
||||||
def guild_infos(self, guild_id: int) -> dict:
|
def guild_infos(self, guild_id: int) -> dict:
|
||||||
@ -181,7 +181,7 @@ class DiscordClient:
|
|||||||
return r.json()
|
return r.json()
|
||||||
|
|
||||||
def guild_name(self, guild_id: int, use_cache: bool = True) -> str:
|
def guild_name(self, guild_id: int, use_cache: bool = True) -> str:
|
||||||
"""returns the name of this guild (cached)
|
"""returns the name of this guild (cached)
|
||||||
or an empty string if something went wrong
|
or an empty string if something went wrong
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
@ -198,8 +198,8 @@ class DiscordClient:
|
|||||||
if 'name' in guild_infos:
|
if 'name' in guild_infos:
|
||||||
guild_name = guild_infos['name']
|
guild_name = guild_infos['name']
|
||||||
self._redis.set(
|
self._redis.set(
|
||||||
name=key_name,
|
name=key_name,
|
||||||
value=guild_name,
|
value=guild_name,
|
||||||
ex=DISCORD_GUILD_NAME_CACHE_MAX_AGE
|
ex=DISCORD_GUILD_NAME_CACHE_MAX_AGE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -208,7 +208,7 @@ class DiscordClient:
|
|||||||
return guild_name
|
return guild_name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _guild_name_cache_key(cls, guild_id: int) -> str:
|
def _guild_name_cache_key(cls, guild_id: int) -> str:
|
||||||
"""Returns key for accessing role given by name in the role cache"""
|
"""Returns key for accessing role given by name in the role cache"""
|
||||||
gen_key = DiscordClient._generate_hash(f'{guild_id}')
|
gen_key = DiscordClient._generate_hash(f'{guild_id}')
|
||||||
return f'{cls._KEYPREFIX_GUILD_NAME}__{gen_key}'
|
return f'{cls._KEYPREFIX_GUILD_NAME}__{gen_key}'
|
||||||
@ -217,38 +217,38 @@ class DiscordClient:
|
|||||||
|
|
||||||
def guild_roles(self, guild_id: int, use_cache: bool = True) -> list:
|
def guild_roles(self, guild_id: int, use_cache: bool = True) -> list:
|
||||||
"""Returns the list of all roles for this guild
|
"""Returns the list of all roles for this guild
|
||||||
|
|
||||||
If use_cache is set to False it will always hit the API to retrieve
|
If use_cache is set to False it will always hit the API to retrieve
|
||||||
fresh data and update the cache
|
fresh data and update the cache
|
||||||
"""
|
"""
|
||||||
cache_key = self._guild_roles_cache_key(guild_id)
|
cache_key = self._guild_roles_cache_key(guild_id)
|
||||||
if use_cache:
|
if use_cache:
|
||||||
roles_raw = self._redis.get(name=cache_key)
|
roles_raw = self._redis.get(name=cache_key)
|
||||||
if roles_raw:
|
if roles_raw:
|
||||||
logger.debug('Returning roles for guild %s from cache', guild_id)
|
logger.debug('Returning roles for guild %s from cache', guild_id)
|
||||||
return json.loads(self._redis_decode(roles_raw))
|
return json.loads(self._redis_decode(roles_raw))
|
||||||
else:
|
else:
|
||||||
logger.debug('No roles for guild %s in cache', guild_id)
|
logger.debug('No roles for guild %s in cache', guild_id)
|
||||||
|
|
||||||
route = f"guilds/{guild_id}/roles"
|
route = f"guilds/{guild_id}/roles"
|
||||||
r = self._api_request(method='get', route=route)
|
r = self._api_request(method='get', route=route)
|
||||||
roles = r.json()
|
roles = r.json()
|
||||||
if roles and isinstance(roles, list):
|
if roles and isinstance(roles, list):
|
||||||
self._redis.set(
|
self._redis.set(
|
||||||
name=cache_key,
|
name=cache_key,
|
||||||
value=json.dumps(roles),
|
value=json.dumps(roles),
|
||||||
ex=DISCORD_ROLES_CACHE_MAX_AGE
|
ex=DISCORD_ROLES_CACHE_MAX_AGE
|
||||||
)
|
)
|
||||||
return roles
|
return roles
|
||||||
|
|
||||||
def create_guild_role(self, guild_id: int, role_name: str, **kwargs) -> dict:
|
def create_guild_role(self, guild_id: int, role_name: str, **kwargs) -> dict:
|
||||||
"""Create a new guild role with the given name.
|
"""Create a new guild role with the given name.
|
||||||
See official documentation for additional optional parameters.
|
See official documentation for additional optional parameters.
|
||||||
|
|
||||||
Note that Discord allows the creation of multiple roles with the same name,
|
Note that Discord allows the creation of multiple roles with the same name,
|
||||||
so to avoid duplicates it's important to check existing roles
|
so to avoid duplicates it's important to check existing roles
|
||||||
before creating new one
|
before creating new one
|
||||||
|
|
||||||
returns a new role dict on success
|
returns a new role dict on success
|
||||||
"""
|
"""
|
||||||
route = f"guilds/{guild_id}/roles"
|
route = f"guilds/{guild_id}/roles"
|
||||||
@ -269,9 +269,9 @@ class DiscordClient:
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _invalidate_guild_roles_cache(self, guild_id: int) -> None:
|
def _invalidate_guild_roles_cache(self, guild_id: int) -> None:
|
||||||
cache_key = self._guild_roles_cache_key(guild_id)
|
cache_key = self._guild_roles_cache_key(guild_id)
|
||||||
self._redis.delete(cache_key)
|
self._redis.delete(cache_key)
|
||||||
logger.debug('Guild roles cache invalidated')
|
logger.debug('Guild roles cache invalidated')
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ class DiscordClient:
|
|||||||
"""Returns key for accessing cached roles for a guild"""
|
"""Returns key for accessing cached roles for a guild"""
|
||||||
gen_key = cls._generate_hash(f'{guild_id}')
|
gen_key = cls._generate_hash(f'{guild_id}')
|
||||||
return f'{cls._KEYPREFIX_GUILD_ROLES}__{gen_key}'
|
return f'{cls._KEYPREFIX_GUILD_ROLES}__{gen_key}'
|
||||||
|
|
||||||
def match_role_from_name(self, guild_id: int, role_name: str) -> dict:
|
def match_role_from_name(self, guild_id: int, role_name: str) -> dict:
|
||||||
"""returns Discord role matching the given name or an empty dict"""
|
"""returns Discord role matching the given name or an empty dict"""
|
||||||
guild_roles = DiscordRoles(self.guild_roles(guild_id))
|
guild_roles = DiscordRoles(self.guild_roles(guild_id))
|
||||||
@ -288,12 +288,12 @@ class DiscordClient:
|
|||||||
|
|
||||||
def match_or_create_roles_from_names(self, guild_id: int, role_names: list) -> list:
|
def match_or_create_roles_from_names(self, guild_id: int, role_names: list) -> list:
|
||||||
"""returns Discord roles matching the given names
|
"""returns Discord roles matching the given names
|
||||||
|
|
||||||
Returns as list of tuple of role and created flag
|
Returns as list of tuple of role and created flag
|
||||||
|
|
||||||
Will try to match with existing roles names
|
Will try to match with existing roles names
|
||||||
Non-existing roles will be created, then created flag will be True
|
Non-existing roles will be created, then created flag will be True
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- guild_id: ID of guild
|
- guild_id: ID of guild
|
||||||
- role_names: list of name strings each defining a role
|
- role_names: list of name strings each defining a role
|
||||||
@ -305,7 +305,7 @@ class DiscordClient:
|
|||||||
}
|
}
|
||||||
for role_name in role_names_cleaned:
|
for role_name in role_names_cleaned:
|
||||||
role, created = self.match_or_create_role_from_name(
|
role, created = self.match_or_create_role_from_name(
|
||||||
guild_id=guild_id,
|
guild_id=guild_id,
|
||||||
role_name=DiscordRoles.sanitize_role_name(role_name),
|
role_name=DiscordRoles.sanitize_role_name(role_name),
|
||||||
guild_roles=guild_roles
|
guild_roles=guild_roles
|
||||||
)
|
)
|
||||||
@ -321,46 +321,46 @@ class DiscordClient:
|
|||||||
"""returns Discord role matching the given name
|
"""returns Discord role matching the given name
|
||||||
|
|
||||||
Returns as tuple of role and created flag
|
Returns as tuple of role and created flag
|
||||||
|
|
||||||
Will try to match with existing roles names
|
Will try to match with existing roles names
|
||||||
Non-existing roles will be created, then created flag will be True
|
Non-existing roles will be created, then created flag will be True
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- guild_id: ID of guild
|
- guild_id: ID of guild
|
||||||
- role_name: strings defining name of a role
|
- role_name: strings defining name of a role
|
||||||
- guild_roles: All known guild roles as DiscordRoles object.
|
- guild_roles: All known guild roles as DiscordRoles object.
|
||||||
Helps to void redundant lookups of guild roles
|
Helps to void redundant lookups of guild roles
|
||||||
when this method is used multiple times.
|
when this method is used multiple times.
|
||||||
"""
|
"""
|
||||||
if not isinstance(role_name, str):
|
if not isinstance(role_name, str):
|
||||||
raise TypeError('role_name must be of type string')
|
raise TypeError('role_name must be of type string')
|
||||||
|
|
||||||
created = False
|
created = False
|
||||||
if guild_roles is None:
|
if guild_roles is None:
|
||||||
guild_roles = DiscordRoles(self.guild_roles(guild_id))
|
guild_roles = DiscordRoles(self.guild_roles(guild_id))
|
||||||
role = guild_roles.role_by_name(role_name)
|
role = guild_roles.role_by_name(role_name)
|
||||||
if not role:
|
if not role:
|
||||||
if not DISCORD_DISABLE_ROLE_CREATION:
|
if not DISCORD_DISABLE_ROLE_CREATION:
|
||||||
logger.debug('Need to create missing role: %s', role_name)
|
logger.debug('Need to create missing role: %s', role_name)
|
||||||
role = self.create_guild_role(guild_id, role_name)
|
role = self.create_guild_role(guild_id, role_name)
|
||||||
created = True
|
created = True
|
||||||
else:
|
else:
|
||||||
role = None
|
role = None
|
||||||
|
|
||||||
return role, created
|
return role, created
|
||||||
|
|
||||||
# guild members
|
# guild members
|
||||||
|
|
||||||
def add_guild_member(
|
def add_guild_member(
|
||||||
self,
|
self,
|
||||||
guild_id: int,
|
guild_id: int,
|
||||||
user_id: int,
|
user_id: int,
|
||||||
access_token: str,
|
access_token: str,
|
||||||
role_ids: list = None,
|
role_ids: list = None,
|
||||||
nick: str = None
|
nick: str = None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Adds a user to the guilds.
|
"""Adds a user to the guilds.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True when a new user was added
|
- True when a new user was added
|
||||||
- None if the user already existed
|
- None if the user already existed
|
||||||
@ -370,13 +370,13 @@ class DiscordClient:
|
|||||||
data = {
|
data = {
|
||||||
'access_token': str(access_token)
|
'access_token': str(access_token)
|
||||||
}
|
}
|
||||||
if role_ids:
|
if role_ids:
|
||||||
data['roles'] = self._sanitize_role_ids(role_ids)
|
data['roles'] = self._sanitize_role_ids(role_ids)
|
||||||
|
|
||||||
if nick:
|
if nick:
|
||||||
data['nick'] = str(nick)[:self._NICK_MAX_CHARS]
|
data['nick'] = str(nick)[:self._NICK_MAX_CHARS]
|
||||||
|
|
||||||
r = self._api_request(method='put', route=route, data=data)
|
r = self._api_request(method='put', route=route, data=data)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
if r.status_code == 201:
|
if r.status_code == 201:
|
||||||
return True
|
return True
|
||||||
@ -384,10 +384,10 @@ class DiscordClient:
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def guild_member(self, guild_id: int, user_id: int) -> dict:
|
def guild_member(self, guild_id: int, user_id: int) -> dict:
|
||||||
"""returns the user info for a guild member
|
"""returns the user info for a guild member
|
||||||
|
|
||||||
or None if the user is not a member of the guild
|
or None if the user is not a member of the guild
|
||||||
"""
|
"""
|
||||||
route = f'guilds/{guild_id}/members/{user_id}'
|
route = f'guilds/{guild_id}/members/{user_id}'
|
||||||
@ -411,14 +411,14 @@ class DiscordClient:
|
|||||||
"""
|
"""
|
||||||
if not role_ids and not nick:
|
if not role_ids and not nick:
|
||||||
raise ValueError('Must specify role_ids or nick')
|
raise ValueError('Must specify role_ids or nick')
|
||||||
|
|
||||||
if role_ids and not isinstance(role_ids, list):
|
if role_ids and not isinstance(role_ids, list):
|
||||||
raise TypeError('role_ids must be a list type')
|
raise TypeError('role_ids must be a list type')
|
||||||
|
|
||||||
data = dict()
|
data = dict()
|
||||||
if role_ids:
|
if role_ids:
|
||||||
data['roles'] = self._sanitize_role_ids(role_ids)
|
data['roles'] = self._sanitize_role_ids(role_ids)
|
||||||
|
|
||||||
if nick:
|
if nick:
|
||||||
data['nick'] = self._sanitize_nick(nick)
|
data['nick'] = self._sanitize_nick(nick)
|
||||||
|
|
||||||
@ -431,7 +431,7 @@ class DiscordClient:
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
if r.status_code == 204:
|
if r.status_code == 204:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -439,7 +439,7 @@ class DiscordClient:
|
|||||||
|
|
||||||
def remove_guild_member(self, guild_id: int, user_id: int) -> bool:
|
def remove_guild_member(self, guild_id: int, user_id: int) -> bool:
|
||||||
"""Remove a member from a guild
|
"""Remove a member from a guild
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True when successful
|
- True when successful
|
||||||
- None if member does not exist
|
- None if member does not exist
|
||||||
@ -448,7 +448,7 @@ class DiscordClient:
|
|||||||
route = f"guilds/{guild_id}/members/{user_id}"
|
route = f"guilds/{guild_id}/members/{user_id}"
|
||||||
r = self._api_request(
|
r = self._api_request(
|
||||||
method='delete', route=route, raise_for_status=False
|
method='delete', route=route, raise_for_status=False
|
||||||
)
|
)
|
||||||
if self._is_member_unknown_error(r):
|
if self._is_member_unknown_error(r):
|
||||||
logger.warning('User ID %s is not a member of this guild', user_id)
|
logger.warning('User ID %s is not a member of this guild', user_id)
|
||||||
return None
|
return None
|
||||||
@ -461,12 +461,12 @@ class DiscordClient:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Guild member roles
|
# Guild member roles
|
||||||
|
|
||||||
def add_guild_member_role(
|
def add_guild_member_role(
|
||||||
self, guild_id: int, user_id: int, role_id: int
|
self, guild_id: int, user_id: int, role_id: int
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Adds a role to a guild member
|
"""Adds a role to a guild member
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True when successful
|
- True when successful
|
||||||
- None if member does not exist
|
- None if member does not exist
|
||||||
@ -479,7 +479,7 @@ class DiscordClient:
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
if r.status_code == 204:
|
if r.status_code == 204:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -489,7 +489,7 @@ class DiscordClient:
|
|||||||
self, guild_id: int, user_id: int, role_id: int
|
self, guild_id: int, user_id: int, role_id: int
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Removes a role to a guild member
|
"""Removes a role to a guild member
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True when successful
|
- True when successful
|
||||||
- None if member does not exist
|
- None if member does not exist
|
||||||
@ -517,31 +517,31 @@ class DiscordClient:
|
|||||||
)
|
)
|
||||||
except (ValueError, KeyError):
|
except (ValueError, KeyError):
|
||||||
result = False
|
result = False
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Internal methods
|
# Internal methods
|
||||||
|
|
||||||
def _api_request(
|
def _api_request(
|
||||||
self,
|
self,
|
||||||
method: str,
|
method: str,
|
||||||
route: str,
|
route: str,
|
||||||
data: dict = None,
|
data: dict = None,
|
||||||
authorization: str = None,
|
authorization: str = None,
|
||||||
raise_for_status: bool = True
|
raise_for_status: bool = True
|
||||||
) -> requests.Response:
|
) -> requests.Response:
|
||||||
"""Core method for performing all API calls"""
|
"""Core method for performing all API calls"""
|
||||||
uid = uuid1().hex
|
uid = uuid1().hex
|
||||||
|
|
||||||
if not hasattr(requests, method):
|
if not hasattr(requests, method):
|
||||||
raise ValueError('Invalid method: %s' % method)
|
raise ValueError('Invalid method: %s' % method)
|
||||||
|
|
||||||
if not authorization:
|
if not authorization:
|
||||||
authorization = f'Bot {self.access_token}'
|
authorization = f'Bot {self.access_token}'
|
||||||
|
|
||||||
self._handle_ongoing_api_backoff(uid)
|
self._handle_ongoing_api_backoff(uid)
|
||||||
if self.is_rate_limited:
|
if self.is_rate_limited:
|
||||||
self._ensure_rate_limed_not_exhausted(uid)
|
self._ensure_rate_limed_not_exhausted(uid)
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent': f'{AUTH_TITLE} ({__url__}, {__version__})',
|
'User-Agent': f'{AUTH_TITLE} ({__url__}, {__version__})',
|
||||||
'accept': 'application/json',
|
'accept': 'application/json',
|
||||||
@ -559,21 +559,21 @@ class DiscordClient:
|
|||||||
}
|
}
|
||||||
if data:
|
if data:
|
||||||
args['json'] = data
|
args['json'] = data
|
||||||
|
|
||||||
logger.info('%s: sending %s request to url \'%s\'', uid, method.upper(), url)
|
logger.info('%s: sending %s request to url \'%s\'', uid, method.upper(), url)
|
||||||
logger.debug('%s: request headers: %s', uid, headers)
|
logger.debug('%s: request headers: %s', uid, headers)
|
||||||
r = getattr(requests, method)(**args)
|
r = getattr(requests, method)(**args)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'%s: returned status code %d with headers: %s',
|
'%s: returned status code %d with headers: %s',
|
||||||
uid,
|
uid,
|
||||||
r.status_code,
|
r.status_code,
|
||||||
r.headers
|
r.headers
|
||||||
)
|
)
|
||||||
logger.debug('%s: response:\n%s', uid, r.text)
|
logger.debug('%s: response:\n%s', uid, r.text)
|
||||||
if not r.ok:
|
if not r.ok:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'%s: Discord API returned error code %d and this response: %s',
|
'%s: Discord API returned error code %d and this response: %s',
|
||||||
uid,
|
uid,
|
||||||
r.status_code,
|
r.status_code,
|
||||||
r.text
|
r.text
|
||||||
)
|
)
|
||||||
@ -582,15 +582,15 @@ class DiscordClient:
|
|||||||
self._handle_new_api_backoff(r, uid)
|
self._handle_new_api_backoff(r, uid)
|
||||||
|
|
||||||
self._report_rate_limit_from_api(r, uid)
|
self._report_rate_limit_from_api(r, uid)
|
||||||
|
|
||||||
if raise_for_status:
|
if raise_for_status:
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def _handle_ongoing_api_backoff(self, uid: str) -> None:
|
def _handle_ongoing_api_backoff(self, uid: str) -> None:
|
||||||
"""checks if api is currently on backoff
|
"""checks if api is currently on backoff
|
||||||
if on backoff: will do a blocking wait if it expires soon,
|
if on backoff: will do a blocking wait if it expires soon,
|
||||||
else raises exception
|
else raises exception
|
||||||
"""
|
"""
|
||||||
global_backoff_duration = self._redis.pttl(self._KEY_GLOBAL_BACKOFF_UNTIL)
|
global_backoff_duration = self._redis.pttl(self._KEY_GLOBAL_BACKOFF_UNTIL)
|
||||||
@ -611,52 +611,52 @@ class DiscordClient:
|
|||||||
raise DiscordTooManyRequestsError(retry_after=global_backoff_duration)
|
raise DiscordTooManyRequestsError(retry_after=global_backoff_duration)
|
||||||
|
|
||||||
def _ensure_rate_limed_not_exhausted(self, uid: str) -> int:
|
def _ensure_rate_limed_not_exhausted(self, uid: str) -> int:
|
||||||
"""ensures that the rate limit is not exhausted
|
"""ensures that the rate limit is not exhausted
|
||||||
if exhausted: will do a blocking wait if rate limit resets soon,
|
if exhausted: will do a blocking wait if rate limit resets soon,
|
||||||
else raises exception
|
else raises exception
|
||||||
|
|
||||||
returns requests remaining on success
|
returns requests remaining on success
|
||||||
"""
|
"""
|
||||||
for _ in range(RATE_LIMIT_RETRIES):
|
for _ in range(RATE_LIMIT_RETRIES):
|
||||||
requests_remaining = self._redis_decr_or_set(
|
requests_remaining = self._redis_decr_or_set(
|
||||||
name=self._KEY_GLOBAL_RATE_LIMIT_REMAINING,
|
name=self._KEY_GLOBAL_RATE_LIMIT_REMAINING,
|
||||||
value=RATE_LIMIT_MAX_REQUESTS,
|
value=RATE_LIMIT_MAX_REQUESTS,
|
||||||
px=RATE_LIMIT_RESETS_AFTER + DURATION_CONTINGENCY
|
px=RATE_LIMIT_RESETS_AFTER + DURATION_CONTINGENCY
|
||||||
)
|
)
|
||||||
resets_in = max(
|
resets_in = max(
|
||||||
MINIMUM_BLOCKING_WAIT,
|
MINIMUM_BLOCKING_WAIT,
|
||||||
self._redis.pttl(self._KEY_GLOBAL_RATE_LIMIT_REMAINING)
|
self._redis.pttl(self._KEY_GLOBAL_RATE_LIMIT_REMAINING)
|
||||||
)
|
)
|
||||||
if requests_remaining >= 0:
|
if requests_remaining >= 0:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'%s: Got one of %d remaining requests until reset in %s ms',
|
'%s: Got one of %d remaining requests until reset in %s ms',
|
||||||
uid,
|
uid,
|
||||||
requests_remaining + 1,
|
requests_remaining + 1,
|
||||||
resets_in
|
resets_in
|
||||||
)
|
)
|
||||||
return requests_remaining
|
return requests_remaining
|
||||||
|
|
||||||
elif resets_in < WAIT_THRESHOLD:
|
elif resets_in < WAIT_THRESHOLD:
|
||||||
sleep(resets_in / 1000)
|
sleep(resets_in / 1000)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'%s: No requests remaining until reset in %d ms. '
|
'%s: No requests remaining until reset in %d ms. '
|
||||||
'Waiting for reset.',
|
'Waiting for reset.',
|
||||||
uid,
|
uid,
|
||||||
resets_in
|
resets_in
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'%s: No requests remaining until reset in %d ms. '
|
'%s: No requests remaining until reset in %d ms. '
|
||||||
'Raising exception.',
|
'Raising exception.',
|
||||||
uid,
|
uid,
|
||||||
resets_in
|
resets_in
|
||||||
)
|
)
|
||||||
raise DiscordRateLimitExhausted(resets_in)
|
raise DiscordRateLimitExhausted(resets_in)
|
||||||
|
|
||||||
raise RuntimeError('Failed to handle rate limit after after too tries.')
|
raise RuntimeError('Failed to handle rate limit after after too tries.')
|
||||||
|
|
||||||
def _handle_new_api_backoff(self, r: requests.Response, uid: str) -> None:
|
def _handle_new_api_backoff(self, r: requests.Response, uid: str) -> None:
|
||||||
"""raises exception for new API backoff error"""
|
"""raises exception for new API backoff error"""
|
||||||
response = r.json()
|
response = r.json()
|
||||||
@ -669,7 +669,7 @@ class DiscordClient:
|
|||||||
else:
|
else:
|
||||||
retry_after = DEFAULT_BACKOFF_DELAY
|
retry_after = DEFAULT_BACKOFF_DELAY
|
||||||
self._redis_set_if_longer(
|
self._redis_set_if_longer(
|
||||||
name=self._KEY_GLOBAL_BACKOFF_UNTIL,
|
name=self._KEY_GLOBAL_BACKOFF_UNTIL,
|
||||||
value='GLOBAL_API_BACKOFF',
|
value='GLOBAL_API_BACKOFF',
|
||||||
px=retry_after
|
px=retry_after
|
||||||
)
|
)
|
||||||
@ -684,8 +684,8 @@ class DiscordClient:
|
|||||||
"""Tries to log the current rate limit reported from API"""
|
"""Tries to log the current rate limit reported from API"""
|
||||||
if (
|
if (
|
||||||
logger.getEffectiveLevel() <= logging.DEBUG
|
logger.getEffectiveLevel() <= logging.DEBUG
|
||||||
and 'x-ratelimit-limit' in r.headers
|
and 'x-ratelimit-limit' in r.headers
|
||||||
and 'x-ratelimit-remaining' in r.headers
|
and 'x-ratelimit-remaining' in r.headers
|
||||||
and 'x-ratelimit-reset-after' in r.headers
|
and 'x-ratelimit-reset-after' in r.headers
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
@ -701,7 +701,7 @@ class DiscordClient:
|
|||||||
)
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _redis_decode(value: str) -> str:
|
def _redis_decode(value: str) -> str:
|
||||||
"""Decodes a string from Redis and passes through None and Booleans"""
|
"""Decodes a string from Redis and passes through None and Booleans"""
|
||||||
|
|||||||
@ -3,18 +3,18 @@ import math
|
|||||||
|
|
||||||
class DiscordClientException(Exception):
|
class DiscordClientException(Exception):
|
||||||
"""Base Exception for the Discord client"""
|
"""Base Exception for the Discord client"""
|
||||||
|
|
||||||
|
|
||||||
class DiscordApiBackoff(DiscordClientException):
|
class DiscordApiBackoff(DiscordClientException):
|
||||||
"""Exception signaling we need to backoff from sending requests to the API for now
|
"""Exception signaling we need to backoff from sending requests to the API for now
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, retry_after: int):
|
def __init__(self, retry_after: int):
|
||||||
"""
|
"""
|
||||||
:param retry_after: int time to retry after in milliseconds
|
:param retry_after: int time to retry after in milliseconds
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.retry_after = int(retry_after)
|
self.retry_after = int(retry_after)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def retry_after_seconds(self):
|
def retry_after_seconds(self):
|
||||||
@ -22,12 +22,12 @@ class DiscordApiBackoff(DiscordClientException):
|
|||||||
|
|
||||||
|
|
||||||
class DiscordRateLimitExhausted(DiscordApiBackoff):
|
class DiscordRateLimitExhausted(DiscordApiBackoff):
|
||||||
"""Exception signaling that the total number of requests allowed under the
|
"""Exception signaling that the total number of requests allowed under the
|
||||||
current rate limit have been exhausted and weed to wait until next reset.
|
current rate limit have been exhausted and weed to wait until next reset.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class DiscordTooManyRequestsError(DiscordApiBackoff):
|
class DiscordTooManyRequestsError(DiscordApiBackoff):
|
||||||
"""API has responded with a 429 Too Many Requests Error.
|
"""API has responded with a 429 Too Many Requests Error.
|
||||||
Need to backoff for now.
|
Need to backoff for now.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -3,10 +3,10 @@ from copy import copy
|
|||||||
|
|
||||||
class DiscordRoles:
|
class DiscordRoles:
|
||||||
"""Container class that helps dealing with Discord roles.
|
"""Container class that helps dealing with Discord roles.
|
||||||
|
|
||||||
Objects of this class are immutable and work in many ways like sets.
|
Objects of this class are immutable and work in many ways like sets.
|
||||||
|
|
||||||
Ideally objects are initialized from raw API responses,
|
Ideally objects are initialized from raw API responses,
|
||||||
e.g. from DiscordClient.guild.roles()
|
e.g. from DiscordClient.guild.roles()
|
||||||
"""
|
"""
|
||||||
_ROLE_NAME_MAX_CHARS = 100
|
_ROLE_NAME_MAX_CHARS = 100
|
||||||
@ -21,7 +21,7 @@ class DiscordRoles:
|
|||||||
self._assert_valid_role(role)
|
self._assert_valid_role(role)
|
||||||
self._roles[int(role['id'])] = role
|
self._roles[int(role['id'])] = role
|
||||||
self._roles_by_name[self.sanitize_role_name(role['name'])] = role
|
self._roles_by_name[self.sanitize_role_name(role['name'])] = role
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, type(self)):
|
if isinstance(other, type(self)):
|
||||||
return self.ids() == other.ids()
|
return self.ids() == other.ids()
|
||||||
@ -29,31 +29,31 @@ class DiscordRoles:
|
|||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(tuple(sorted(self._roles.keys())))
|
return hash(tuple(sorted(self._roles.keys())))
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for role in self._roles.values():
|
for role in self._roles.values():
|
||||||
yield role
|
yield role
|
||||||
|
|
||||||
def __contains__(self, item) -> bool:
|
def __contains__(self, item) -> bool:
|
||||||
return int(item) in self._roles
|
return int(item) in self._roles
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._roles.keys())
|
return len(self._roles.keys())
|
||||||
|
|
||||||
def has_roles(self, role_ids: set) -> bool:
|
def has_roles(self, role_ids: set) -> bool:
|
||||||
"""returns true if this objects contains all roles defined by given role_ids
|
"""returns true if this objects contains all roles defined by given role_ids
|
||||||
incl. managed roles
|
incl. managed roles
|
||||||
"""
|
"""
|
||||||
role_ids = {int(id) for id in role_ids}
|
role_ids = {int(id) for id in role_ids}
|
||||||
all_role_ids = self._roles.keys()
|
all_role_ids = self._roles.keys()
|
||||||
return role_ids.issubset(all_role_ids)
|
return role_ids.issubset(all_role_ids)
|
||||||
|
|
||||||
def ids(self) -> set:
|
def ids(self) -> set:
|
||||||
"""return a set of all role IDs"""
|
"""return a set of all role IDs"""
|
||||||
return set(self._roles.keys())
|
return set(self._roles.keys())
|
||||||
|
|
||||||
def subset(self, role_ids: set = None, managed_only: bool = False) -> object:
|
def subset(self, role_ids: set = None, managed_only: bool = False) -> object:
|
||||||
"""returns a new object containing the subset of roles as defined
|
"""returns a new object containing the subset of roles as defined
|
||||||
by given role IDs and/or including managed roles only
|
by given role IDs and/or including managed roles only
|
||||||
"""
|
"""
|
||||||
if role_ids is not None:
|
if role_ids is not None:
|
||||||
@ -68,23 +68,23 @@ class DiscordRoles:
|
|||||||
return type(self)([
|
return type(self)([
|
||||||
role for _, role in self._roles.items() if role['managed']
|
role for _, role in self._roles.items() if role['managed']
|
||||||
])
|
])
|
||||||
|
|
||||||
elif role_ids is not None and managed_only:
|
elif role_ids is not None and managed_only:
|
||||||
return type(self)([
|
return type(self)([
|
||||||
role for role_id, role in self._roles.items()
|
role for role_id, role in self._roles.items()
|
||||||
if role_id in role_ids and role['managed']
|
if role_id in role_ids and role['managed']
|
||||||
])
|
])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return copy(self)
|
return copy(self)
|
||||||
|
|
||||||
def union(self, other: object) -> object:
|
def union(self, other: object) -> object:
|
||||||
"""returns a new roles object that is the union of this roles object
|
"""returns a new roles object that is the union of this roles object
|
||||||
with other"""
|
with other"""
|
||||||
return type(self)(list(self) + list(other))
|
return type(self)(list(self) + list(other))
|
||||||
|
|
||||||
def difference(self, other: object) -> object:
|
def difference(self, other: object) -> object:
|
||||||
"""returns a new roles object that only contains the roles
|
"""returns a new roles object that only contains the roles
|
||||||
that exist in the current objects, but not in other
|
that exist in the current objects, but not in other
|
||||||
"""
|
"""
|
||||||
new_ids = self.ids().difference(other.ids())
|
new_ids = self.ids().difference(other.ids())
|
||||||
@ -97,11 +97,11 @@ class DiscordRoles:
|
|||||||
return self._roles_by_name[role_name]
|
return self._roles_by_name[role_name]
|
||||||
else:
|
else:
|
||||||
return dict()
|
return dict()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_from_matched_roles(cls, matched_roles: list) -> None:
|
def create_from_matched_roles(cls, matched_roles: list) -> None:
|
||||||
"""returns a new object created from the given list of matches roles
|
"""returns a new object created from the given list of matches roles
|
||||||
|
|
||||||
matches_roles must be a list of tuples in the form: (role, created)
|
matches_roles must be a list of tuples in the form: (role, created)
|
||||||
"""
|
"""
|
||||||
raw_roles = [x[0] for x in matched_roles]
|
raw_roles = [x[0] for x in matched_roles]
|
||||||
@ -111,10 +111,10 @@ class DiscordRoles:
|
|||||||
def _assert_valid_role(role: dict):
|
def _assert_valid_role(role: dict):
|
||||||
if not isinstance(role, dict):
|
if not isinstance(role, dict):
|
||||||
raise TypeError('Roles must be of type dict: %s' % role)
|
raise TypeError('Roles must be of type dict: %s' % role)
|
||||||
|
|
||||||
if 'id' not in role or 'name' not in role or 'managed' not in role:
|
if 'id' not in role or 'name' not in role or 'managed' not in role:
|
||||||
raise ValueError('This role is not valid: %s' % role)
|
raise ValueError('This role is not valid: %s' % role)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def sanitize_role_name(cls, role_name: str) -> str:
|
def sanitize_role_name(cls, role_name: str) -> str:
|
||||||
"""shortens too long strings if necessary"""
|
"""shortens too long strings if necessary"""
|
||||||
|
|||||||
@ -27,8 +27,8 @@ ALL_ROLES = [ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE]
|
|||||||
|
|
||||||
|
|
||||||
def create_user_info(
|
def create_user_info(
|
||||||
id: int = TEST_USER_ID,
|
id: int = TEST_USER_ID,
|
||||||
username: str = TEST_USER_NAME,
|
username: str = TEST_USER_NAME,
|
||||||
discriminator: str = TEST_USER_DISCRIMINATOR
|
discriminator: str = TEST_USER_DISCRIMINATOR
|
||||||
):
|
):
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -5,11 +5,11 @@ The results can be analysed in a special log file.
|
|||||||
|
|
||||||
This script is design to be run manually as unit test, e.g. by running the following:
|
This script is design to be run manually as unit test, e.g. by running the following:
|
||||||
|
|
||||||
python manage.py test
|
python manage.py test
|
||||||
allianceauth.services.modules.discord.discord_client.tests.piloting_concurrency
|
allianceauth.services.modules.discord.discord_client.tests.piloting_concurrency
|
||||||
|
|
||||||
To make it work please set the below mentioned environment variables for your server.
|
To make it work please set the below mentioned environment variables for your server.
|
||||||
Since this may cause lots of 429s we'd recommend NOT to use your
|
Since this may cause lots of 429s we'd recommend NOT to use your
|
||||||
alliance Discord server for this.
|
alliance Discord server for this.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ def worker(num: int):
|
|||||||
client = DiscordClient(DISCORD_BOT_TOKEN)
|
client = DiscordClient(DISCORD_BOT_TOKEN)
|
||||||
try:
|
try:
|
||||||
runs = 0
|
runs = 0
|
||||||
while runs < NUMBER_OF_RUNS:
|
while runs < NUMBER_OF_RUNS:
|
||||||
run_info = '%s: run %d' % (worker_info, runs + 1)
|
run_info = '%s: run %d' % (worker_info, runs + 1)
|
||||||
my_jitter_secs = random() * MAX_JITTER_PER_RUN_SECS
|
my_jitter_secs = random() * MAX_JITTER_PER_RUN_SECS
|
||||||
logger.info('%s - waiting %s secs', run_info, f'{my_jitter_secs:.3f}')
|
logger.info('%s - waiting %s secs', run_info, f'{my_jitter_secs:.3f}')
|
||||||
@ -67,18 +67,18 @@ def worker(num: int):
|
|||||||
logger.info(message)
|
logger.info(message)
|
||||||
print()
|
print()
|
||||||
print(message)
|
print(message)
|
||||||
sleep(bo.retry_after / 1000)
|
sleep(bo.retry_after / 1000)
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logger.exception('%s: Processing aborted: %s', worker_info, ex)
|
logger.exception('%s: Processing aborted: %s', worker_info, ex)
|
||||||
|
|
||||||
logger.info('%s: finished', worker_info)
|
logger.info('%s: finished', worker_info)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class TestMulti(TestCase):
|
class TestMulti(TestCase):
|
||||||
|
|
||||||
def test_multi(self):
|
def test_multi(self):
|
||||||
logger.info('Starting multi test')
|
logger.info('Starting multi test')
|
||||||
for num in range(NUMBER_OF_WORKERS):
|
for num in range(NUMBER_OF_WORKERS):
|
||||||
x = threading.Thread(target=worker, args=(num + 1,))
|
x = threading.Thread(target=worker, args=(num + 1,))
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""This script is for functional testing of the Discord client with a Discord server
|
"""This script is for functional testing of the Discord client with a Discord server
|
||||||
|
|
||||||
It will run single requests of the various functions to validate
|
It will run single requests of the various functions to validate
|
||||||
that they actually work - excluding those that require Oauth, or does not work
|
that they actually work - excluding those that require Oauth, or does not work
|
||||||
with a bot token. The results can be also seen in a special log file.
|
with a bot token. The results can be also seen in a special log file.
|
||||||
|
|
||||||
This script is design to be run manually as unit test, e.g. by running the following:
|
This script is design to be run manually as unit test, e.g. by running the following:
|
||||||
@ -10,7 +10,7 @@ python manage.py test
|
|||||||
allianceauth.services.modules.discord.discord_self.client.tests.piloting_functionality
|
allianceauth.services.modules.discord.discord_self.client.tests.piloting_functionality
|
||||||
|
|
||||||
To make it work please set the below mentioned environment variables for your server.
|
To make it work please set the below mentioned environment variables for your server.
|
||||||
Since this may cause lots of 429s we'd recommend NOT to use your
|
Since this may cause lots of 429s we'd recommend NOT to use your
|
||||||
alliance Discord server for this.
|
alliance Discord server for this.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class TestDiscordApiLive(TestCase):
|
|||||||
"""runs features that have not been run in any of the other tests"""
|
"""runs features that have not been run in any of the other tests"""
|
||||||
self.client.guild_infos(DISCORD_GUILD_ID)
|
self.client.guild_infos(DISCORD_GUILD_ID)
|
||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
|
|
||||||
self.client.guild_name(DISCORD_GUILD_ID)
|
self.client.guild_name(DISCORD_GUILD_ID)
|
||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
|
|
||||||
@ -57,9 +57,9 @@ class TestDiscordApiLive(TestCase):
|
|||||||
DISCORD_GUILD_ID, ['Testrole A', 'Testrole B']
|
DISCORD_GUILD_ID, ['Testrole A', 'Testrole B']
|
||||||
)
|
)
|
||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
|
|
||||||
def test_create_and_remove_roles(self):
|
def test_create_and_remove_roles(self):
|
||||||
# get base
|
# get base
|
||||||
logger.info('guild_roles')
|
logger.info('guild_roles')
|
||||||
expected = {role['id'] for role in self.client.guild_roles(DISCORD_GUILD_ID)}
|
expected = {role['id'] for role in self.client.guild_roles(DISCORD_GUILD_ID)}
|
||||||
|
|
||||||
@ -70,8 +70,8 @@ class TestDiscordApiLive(TestCase):
|
|||||||
guild_id=DISCORD_GUILD_ID, role_name=role_name
|
guild_id=DISCORD_GUILD_ID, role_name=role_name
|
||||||
)
|
)
|
||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
self.assertEqual(new_role['name'], role_name)
|
self.assertEqual(new_role['name'], role_name)
|
||||||
|
|
||||||
# remove role again
|
# remove role again
|
||||||
logger.info('delete_guild_role')
|
logger.info('delete_guild_role')
|
||||||
self.client.delete_guild_role(
|
self.client.delete_guild_role(
|
||||||
@ -102,7 +102,7 @@ class TestDiscordApiLive(TestCase):
|
|||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
self.assertEqual(user['nick'], new_nick)
|
self.assertEqual(user['nick'], new_nick)
|
||||||
|
|
||||||
def test_member_add_remove_roles(self):
|
def test_member_add_remove_roles(self):
|
||||||
# create new guild role
|
# create new guild role
|
||||||
logger.info('create_guild_role')
|
logger.info('create_guild_role')
|
||||||
new_role = self.client.create_guild_role(
|
new_role = self.client.create_guild_role(
|
||||||
@ -110,7 +110,7 @@ class TestDiscordApiLive(TestCase):
|
|||||||
)
|
)
|
||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
new_role_id = new_role['id']
|
new_role_id = new_role['id']
|
||||||
|
|
||||||
# add to member
|
# add to member
|
||||||
logger.info('add_guild_member_role')
|
logger.info('add_guild_member_role')
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@ -119,7 +119,7 @@ class TestDiscordApiLive(TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
sleep(RATE_LIMIT_DELAY_SECS)
|
sleep(RATE_LIMIT_DELAY_SECS)
|
||||||
|
|
||||||
# remove again
|
# remove again
|
||||||
logger.info('remove_guild_member_role')
|
logger.info('remove_guild_member_role')
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
DiscordApiBackoff,
|
DiscordApiBackoff,
|
||||||
DiscordClientException,
|
DiscordClientException,
|
||||||
DiscordRateLimitExhausted,
|
DiscordRateLimitExhausted,
|
||||||
DiscordTooManyRequestsError
|
DiscordTooManyRequestsError
|
||||||
)
|
)
|
||||||
|
|||||||
@ -25,7 +25,7 @@ class TestDiscordRoles(TestCase):
|
|||||||
def test_raises_exception_if_roles_raw_of_wrong_type(self):
|
def test_raises_exception_if_roles_raw_of_wrong_type(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
DiscordRoles({'id': 1})
|
DiscordRoles({'id': 1})
|
||||||
|
|
||||||
def test_raises_exception_if_list_contains_non_dict(self):
|
def test_raises_exception_if_list_contains_non_dict(self):
|
||||||
roles_raw = [ROLE_ALPHA, 'not_valid']
|
roles_raw = [ROLE_ALPHA, 'not_valid']
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
@ -45,7 +45,7 @@ class TestDiscordRoles(TestCase):
|
|||||||
roles_raw = [{'id': 1, 'name': 'alpha'}]
|
roles_raw = [{'id': 1, 'name': 'alpha'}]
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
DiscordRoles(roles_raw)
|
DiscordRoles(roles_raw)
|
||||||
|
|
||||||
def test_roles_are_equal(self):
|
def test_roles_are_equal(self):
|
||||||
roles_a = DiscordRoles([ROLE_ALPHA, ROLE_BRAVO])
|
roles_a = DiscordRoles([ROLE_ALPHA, ROLE_BRAVO])
|
||||||
roles_b = DiscordRoles([ROLE_ALPHA, ROLE_BRAVO])
|
roles_b = DiscordRoles([ROLE_ALPHA, ROLE_BRAVO])
|
||||||
@ -57,19 +57,19 @@ class TestDiscordRoles(TestCase):
|
|||||||
self.assertNotEqual(roles_a, roles_b)
|
self.assertNotEqual(roles_a, roles_b)
|
||||||
|
|
||||||
def test_different_objects_are_not_equal(self):
|
def test_different_objects_are_not_equal(self):
|
||||||
roles_a = DiscordRoles([ROLE_ALPHA, ROLE_BRAVO])
|
roles_a = DiscordRoles([ROLE_ALPHA, ROLE_BRAVO])
|
||||||
self.assertFalse(roles_a == "invalid")
|
self.assertFalse(roles_a == "invalid")
|
||||||
|
|
||||||
def test_len(self):
|
def test_len(self):
|
||||||
self.assertEqual(len(self.all_roles), 4)
|
self.assertEqual(len(self.all_roles), 4)
|
||||||
|
|
||||||
def test_contains(self):
|
def test_contains(self):
|
||||||
self.assertTrue(1 in self.all_roles)
|
self.assertTrue(1 in self.all_roles)
|
||||||
self.assertFalse(99 in self.all_roles)
|
self.assertFalse(99 in self.all_roles)
|
||||||
|
|
||||||
def test_sanitize_role_name(self):
|
def test_sanitize_role_name(self):
|
||||||
role_name_input = 'x' * 110
|
role_name_input = 'x' * 110
|
||||||
role_name_expected = 'x' * 100
|
role_name_expected = 'x' * 100
|
||||||
result = DiscordRoles.sanitize_role_name(role_name_input)
|
result = DiscordRoles.sanitize_role_name(role_name_input)
|
||||||
self.assertEqual(result, role_name_expected)
|
self.assertEqual(result, role_name_expected)
|
||||||
|
|
||||||
@ -94,8 +94,8 @@ class TestIds(TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.all_roles = DiscordRoles(ALL_ROLES)
|
self.all_roles = DiscordRoles(ALL_ROLES)
|
||||||
|
|
||||||
def test_return_role_ids_default(self):
|
def test_return_role_ids_default(self):
|
||||||
result = self.all_roles.ids()
|
result = self.all_roles.ids()
|
||||||
expected = {1, 2, 3, 13}
|
expected = {1, 2, 3, 13}
|
||||||
self.assertSetEqual(result, expected)
|
self.assertSetEqual(result, expected)
|
||||||
@ -154,7 +154,7 @@ class TestHasRoles(TestCase):
|
|||||||
|
|
||||||
def test_true_if_all_roles_exit_str(self):
|
def test_true_if_all_roles_exit_str(self):
|
||||||
self.assertTrue(self.all_roles.has_roles(['1', '2']))
|
self.assertTrue(self.all_roles.has_roles(['1', '2']))
|
||||||
|
|
||||||
def test_false_if_role_does_not_exit(self):
|
def test_false_if_role_does_not_exit(self):
|
||||||
self.assertFalse(self.all_roles.has_roles([99]))
|
self.assertFalse(self.all_roles.has_roles([99]))
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ class TestHasRoles(TestCase):
|
|||||||
|
|
||||||
def test_true_for_empty_roles(self):
|
def test_true_for_empty_roles(self):
|
||||||
self.assertTrue(self.all_roles.has_roles([]))
|
self.assertTrue(self.all_roles.has_roles([]))
|
||||||
|
|
||||||
|
|
||||||
class TestGetMatchingRolesByName(TestCase):
|
class TestGetMatchingRolesByName(TestCase):
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ from .app_settings import (
|
|||||||
DISCORD_APP_SECRET,
|
DISCORD_APP_SECRET,
|
||||||
DISCORD_BOT_TOKEN,
|
DISCORD_BOT_TOKEN,
|
||||||
DISCORD_CALLBACK_URL,
|
DISCORD_CALLBACK_URL,
|
||||||
DISCORD_GUILD_ID,
|
DISCORD_GUILD_ID,
|
||||||
DISCORD_SYNC_NAMES
|
DISCORD_SYNC_NAMES
|
||||||
)
|
)
|
||||||
from .discord_client import DiscordClient
|
from .discord_client import DiscordClient
|
||||||
@ -41,9 +41,9 @@ class DiscordUserManager(models.Manager):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def add_user(
|
def add_user(
|
||||||
self,
|
self,
|
||||||
user: User,
|
user: User,
|
||||||
authorization_code: str,
|
authorization_code: str,
|
||||||
is_rate_limited: bool = True
|
is_rate_limited: bool = True
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""adds a new Discord user
|
"""adds a new Discord user
|
||||||
@ -52,10 +52,10 @@ class DiscordUserManager(models.Manager):
|
|||||||
- user: Auth user to join
|
- user: Auth user to join
|
||||||
- authorization_code: authorization code returns from oauth
|
- authorization_code: authorization code returns from oauth
|
||||||
- is_rate_limited: When False will disable default rate limiting (use with care)
|
- is_rate_limited: When False will disable default rate limiting (use with care)
|
||||||
|
|
||||||
Returns: True on success, else False or raises exception
|
Returns: True on success, else False or raises exception
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
nickname = self.user_formatted_nick(user) if DISCORD_SYNC_NAMES else None
|
nickname = self.user_formatted_nick(user) if DISCORD_SYNC_NAMES else None
|
||||||
group_names = self.user_group_names(user)
|
group_names = self.user_group_names(user)
|
||||||
access_token = self._exchange_auth_code_for_token(authorization_code)
|
access_token = self._exchange_auth_code_for_token(authorization_code)
|
||||||
@ -63,18 +63,18 @@ class DiscordUserManager(models.Manager):
|
|||||||
discord_user = user_client.current_user()
|
discord_user = user_client.current_user()
|
||||||
user_id = discord_user['id']
|
user_id = discord_user['id']
|
||||||
bot_client = self._bot_client(is_rate_limited=is_rate_limited)
|
bot_client = self._bot_client(is_rate_limited=is_rate_limited)
|
||||||
|
|
||||||
if group_names:
|
if group_names:
|
||||||
role_ids = match_or_create_roles_from_names(
|
role_ids = match_or_create_roles_from_names(
|
||||||
client=bot_client,
|
client=bot_client,
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID,
|
||||||
role_names=group_names
|
role_names=group_names
|
||||||
).ids()
|
).ids()
|
||||||
else:
|
else:
|
||||||
role_ids = None
|
role_ids = None
|
||||||
|
|
||||||
created = bot_client.add_guild_member(
|
created = bot_client.add_guild_member(
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
access_token=access_token,
|
access_token=access_token,
|
||||||
role_ids=role_ids,
|
role_ids=role_ids,
|
||||||
@ -88,10 +88,10 @@ class DiscordUserManager(models.Manager):
|
|||||||
user_id,
|
user_id,
|
||||||
)
|
)
|
||||||
self.update_or_create(
|
self.update_or_create(
|
||||||
user=user,
|
user=user,
|
||||||
defaults={
|
defaults={
|
||||||
'uid': user_id,
|
'uid': user_id,
|
||||||
'username': discord_user['username'][:32],
|
'username': discord_user['username'][:32],
|
||||||
'discriminator': discord_user['discriminator'][:4],
|
'discriminator': discord_user['discriminator'][:4],
|
||||||
'activated': now()
|
'activated': now()
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ class DiscordUserManager(models.Manager):
|
|||||||
or None if user has no main
|
or None if user has no main
|
||||||
"""
|
"""
|
||||||
from .auth_hooks import DiscordService
|
from .auth_hooks import DiscordService
|
||||||
|
|
||||||
if user.profile.main_character:
|
if user.profile.main_character:
|
||||||
return NameFormatter(DiscordService(), user).format_name()
|
return NameFormatter(DiscordService(), user).format_name()
|
||||||
else:
|
else:
|
||||||
@ -139,10 +139,10 @@ class DiscordUserManager(models.Manager):
|
|||||||
"Group names for roles updates of user %s are: %s", user, group_names
|
"Group names for roles updates of user %s are: %s", user, group_names
|
||||||
)
|
)
|
||||||
return group_names
|
return group_names
|
||||||
|
|
||||||
def user_has_account(self, user: User) -> bool:
|
def user_has_account(self, user: User) -> bool:
|
||||||
"""Returns True if the user has an Discord account, else False
|
"""Returns True if the user has an Discord account, else False
|
||||||
|
|
||||||
only checks locally, does not hit the API
|
only checks locally, does not hit the API
|
||||||
"""
|
"""
|
||||||
if not isinstance(user, User):
|
if not isinstance(user, User):
|
||||||
@ -157,7 +157,7 @@ class DiscordUserManager(models.Manager):
|
|||||||
'permissions': str(cls.BOT_PERMISSIONS)
|
'permissions': str(cls.BOT_PERMISSIONS)
|
||||||
|
|
||||||
})
|
})
|
||||||
return f'{DiscordClient.OAUTH_BASE_URL}?{params}'
|
return f'{DiscordClient.OAUTH_BASE_URL}?{params}'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_oauth_redirect_url(cls) -> str:
|
def generate_oauth_redirect_url(cls) -> str:
|
||||||
@ -171,16 +171,16 @@ class DiscordUserManager(models.Manager):
|
|||||||
def _exchange_auth_code_for_token(authorization_code: str) -> str:
|
def _exchange_auth_code_for_token(authorization_code: str) -> str:
|
||||||
oauth = OAuth2Session(DISCORD_APP_ID, redirect_uri=DISCORD_CALLBACK_URL)
|
oauth = OAuth2Session(DISCORD_APP_ID, redirect_uri=DISCORD_CALLBACK_URL)
|
||||||
token = oauth.fetch_token(
|
token = oauth.fetch_token(
|
||||||
DiscordClient.OAUTH_TOKEN_URL,
|
DiscordClient.OAUTH_TOKEN_URL,
|
||||||
client_secret=DISCORD_APP_SECRET,
|
client_secret=DISCORD_APP_SECRET,
|
||||||
code=authorization_code
|
code=authorization_code
|
||||||
)
|
)
|
||||||
logger.debug("Received token from OAuth")
|
logger.debug("Received token from OAuth")
|
||||||
return token['access_token']
|
return token['access_token']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def server_name(cls, use_cache: bool = True) -> str:
|
def server_name(cls, use_cache: bool = True) -> str:
|
||||||
"""returns the name of the current Discord server
|
"""returns the name of the current Discord server
|
||||||
or an empty string if the name could not be retrieved
|
or an empty string if the name could not be retrieved
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
@ -194,7 +194,7 @@ class DiscordUserManager(models.Manager):
|
|||||||
server_name = ""
|
server_name = ""
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Unexpected error when trying to retrieve the server name from Discord",
|
"Unexpected error when trying to retrieve the server name from Discord",
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
server_name = ""
|
server_name = ""
|
||||||
|
|||||||
@ -22,11 +22,11 @@ logger = LoggerAddTag(logging.getLogger(__name__), __title__)
|
|||||||
class DiscordUser(models.Model):
|
class DiscordUser(models.Model):
|
||||||
|
|
||||||
USER_RELATED_NAME = 'discord'
|
USER_RELATED_NAME = 'discord'
|
||||||
|
|
||||||
user = models.OneToOneField(
|
user = models.OneToOneField(
|
||||||
User,
|
User,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name=USER_RELATED_NAME,
|
related_name=USER_RELATED_NAME,
|
||||||
help_text='Auth user owning this Discord account'
|
help_text='Auth user owning this Discord account'
|
||||||
)
|
)
|
||||||
@ -35,21 +35,21 @@ class DiscordUser(models.Model):
|
|||||||
help_text='user\'s ID on Discord'
|
help_text='user\'s ID on Discord'
|
||||||
)
|
)
|
||||||
username = models.CharField(
|
username = models.CharField(
|
||||||
max_length=32,
|
max_length=32,
|
||||||
default='',
|
default='',
|
||||||
blank=True,
|
blank=True,
|
||||||
db_index=True,
|
db_index=True,
|
||||||
help_text='user\'s username on Discord'
|
help_text='user\'s username on Discord'
|
||||||
)
|
)
|
||||||
discriminator = models.CharField(
|
discriminator = models.CharField(
|
||||||
max_length=4,
|
max_length=4,
|
||||||
default='',
|
default='',
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text='user\'s discriminator on Discord'
|
help_text='user\'s discriminator on Discord'
|
||||||
)
|
)
|
||||||
activated = models.DateTimeField(
|
activated = models.DateTimeField(
|
||||||
default=None,
|
default=None,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text='Date & time this service account was activated'
|
help_text='Date & time this service account was activated'
|
||||||
)
|
)
|
||||||
@ -77,11 +77,11 @@ class DiscordUser(models.Model):
|
|||||||
- True on success
|
- True on success
|
||||||
- None if user is no longer a member of the Discord server
|
- None if user is no longer a member of the Discord server
|
||||||
- False on error or raises exception
|
- False on error or raises exception
|
||||||
"""
|
"""
|
||||||
if not nickname:
|
if not nickname:
|
||||||
nickname = DiscordUser.objects.user_formatted_nick(self.user)
|
nickname = DiscordUser.objects.user_formatted_nick(self.user)
|
||||||
if nickname:
|
if nickname:
|
||||||
client = DiscordUser.objects._bot_client()
|
client = DiscordUser.objects._bot_client()
|
||||||
success = client.modify_guild_member(
|
success = client.modify_guild_member(
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID,
|
||||||
user_id=self.uid,
|
user_id=self.uid,
|
||||||
@ -92,14 +92,14 @@ class DiscordUser(models.Model):
|
|||||||
else:
|
else:
|
||||||
logger.warning('Failed to update nickname for %s', self.user)
|
logger.warning('Failed to update nickname for %s', self.user)
|
||||||
return success
|
return success
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def update_groups(self, state_name: str = None) -> bool:
|
def update_groups(self, state_name: str = None) -> bool:
|
||||||
"""update groups for a user based on his current group memberships.
|
"""update groups for a user based on his current group memberships.
|
||||||
Will add or remove roles of a user as needed.
|
Will add or remove roles of a user as needed.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- state_name: optional state name to be used
|
- state_name: optional state name to be used
|
||||||
|
|
||||||
@ -107,13 +107,13 @@ class DiscordUser(models.Model):
|
|||||||
- True on success
|
- True on success
|
||||||
- None if user is no longer a member of the Discord server
|
- None if user is no longer a member of the Discord server
|
||||||
- False on error or raises exception
|
- False on error or raises exception
|
||||||
"""
|
"""
|
||||||
client = DiscordUser.objects._bot_client()
|
client = DiscordUser.objects._bot_client()
|
||||||
member_info = client.guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid)
|
member_info = client.guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid)
|
||||||
if member_info is None:
|
if member_info is None:
|
||||||
# User is no longer a member
|
# User is no longer a member
|
||||||
return None
|
return None
|
||||||
|
|
||||||
guild_roles = DiscordRoles(client.guild_roles(guild_id=DISCORD_GUILD_ID))
|
guild_roles = DiscordRoles(client.guild_roles(guild_id=DISCORD_GUILD_ID))
|
||||||
logger.debug('Current guild roles: %s', guild_roles.ids())
|
logger.debug('Current guild roles: %s', guild_roles.ids())
|
||||||
if 'roles' in member_info:
|
if 'roles' in member_info:
|
||||||
@ -124,17 +124,17 @@ class DiscordUser(models.Model):
|
|||||||
if not guild_roles.has_roles(member_info['roles']):
|
if not guild_roles.has_roles(member_info['roles']):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
'Member %s has unknown roles: %s' % (
|
'Member %s has unknown roles: %s' % (
|
||||||
self.user,
|
self.user,
|
||||||
set(member_info['roles']).difference(guild_roles.ids())
|
set(member_info['roles']).difference(guild_roles.ids())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
member_roles = guild_roles.subset(member_info['roles'])
|
member_roles = guild_roles.subset(member_info['roles'])
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('member_info from %s is not valid' % self.user)
|
raise RuntimeError('member_info from %s is not valid' % self.user)
|
||||||
|
|
||||||
requested_roles = match_or_create_roles_from_names(
|
requested_roles = match_or_create_roles_from_names(
|
||||||
client=client,
|
client=client,
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID,
|
||||||
role_names=DiscordUser.objects.user_group_names(
|
role_names=DiscordUser.objects.user_group_names(
|
||||||
user=self.user, state_name=state_name
|
user=self.user, state_name=state_name
|
||||||
)
|
)
|
||||||
@ -142,7 +142,7 @@ class DiscordUser(models.Model):
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
'Requested roles for user %s: %s', self.user, requested_roles.ids()
|
'Requested roles for user %s: %s', self.user, requested_roles.ids()
|
||||||
)
|
)
|
||||||
logger.debug('Current roles user %s: %s', self.user, member_roles.ids())
|
logger.debug('Current roles user %s: %s', self.user, member_roles.ids())
|
||||||
member_roles_managed = member_roles.subset(managed_only=True)
|
member_roles_managed = member_roles.subset(managed_only=True)
|
||||||
if requested_roles != member_roles.difference(member_roles_managed):
|
if requested_roles != member_roles.difference(member_roles_managed):
|
||||||
logger.debug('Need to update roles for user %s', self.user)
|
logger.debug('Need to update roles for user %s', self.user)
|
||||||
@ -163,25 +163,25 @@ class DiscordUser(models.Model):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def update_username(self) -> bool:
|
def update_username(self) -> bool:
|
||||||
"""Updates the username incl. the discriminator
|
"""Updates the username incl. the discriminator
|
||||||
from the Discord server and saves it
|
from the Discord server and saves it
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True on success
|
- True on success
|
||||||
- None if user is no longer a member of the Discord server
|
- None if user is no longer a member of the Discord server
|
||||||
- False on error or raises exception
|
- False on error or raises exception
|
||||||
"""
|
"""
|
||||||
|
|
||||||
client = DiscordUser.objects._bot_client()
|
client = DiscordUser.objects._bot_client()
|
||||||
user_info = client.guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid)
|
user_info = client.guild_member(guild_id=DISCORD_GUILD_ID, user_id=self.uid)
|
||||||
if user_info is None:
|
if user_info is None:
|
||||||
success = None
|
success = None
|
||||||
elif (
|
elif (
|
||||||
user_info
|
user_info
|
||||||
and 'user' in user_info
|
and 'user' in user_info
|
||||||
and 'username' in user_info['user']
|
and 'username' in user_info['user']
|
||||||
and 'discriminator' in user_info['user']
|
and 'discriminator' in user_info['user']
|
||||||
):
|
):
|
||||||
self.username = user_info['user']['username']
|
self.username = user_info['user']['username']
|
||||||
self.discriminator = user_info['user']['discriminator']
|
self.discriminator = user_info['user']['discriminator']
|
||||||
self.save()
|
self.save()
|
||||||
@ -191,22 +191,22 @@ class DiscordUser(models.Model):
|
|||||||
logger.warning('Failed to update username for %s', self.user)
|
logger.warning('Failed to update username for %s', self.user)
|
||||||
success = False
|
success = False
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def delete_user(
|
def delete_user(
|
||||||
self,
|
self,
|
||||||
notify_user: bool = False,
|
notify_user: bool = False,
|
||||||
is_rate_limited: bool = True,
|
is_rate_limited: bool = True,
|
||||||
handle_api_exceptions: bool = False
|
handle_api_exceptions: bool = False
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Deletes the Discount user both on the server and locally
|
"""Deletes the Discount user both on the server and locally
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- notify_user: When True will sent a notification to the user
|
- notify_user: When True will sent a notification to the user
|
||||||
informing him about the deleting of his account
|
informing him about the deleting of his account
|
||||||
- is_rate_limited: When False will disable default rate limiting (use with care)
|
- is_rate_limited: When False will disable default rate limiting (use with care)
|
||||||
- handle_api_exceptions: When True method will return False
|
- handle_api_exceptions: When True method will return False
|
||||||
when an API exception occurs
|
when an API exception occurs
|
||||||
|
|
||||||
Returns True when successful, otherwise False or raises exceptions
|
Returns True when successful, otherwise False or raises exceptions
|
||||||
Return None if user does no longer exist
|
Return None if user does no longer exist
|
||||||
"""
|
"""
|
||||||
@ -221,8 +221,8 @@ class DiscordUser(models.Model):
|
|||||||
if deleted_count > 0:
|
if deleted_count > 0:
|
||||||
if notify_user:
|
if notify_user:
|
||||||
notify(
|
notify(
|
||||||
user=_user,
|
user=_user,
|
||||||
title=gettext_lazy('Discord Account Disabled'),
|
title=gettext_lazy('Discord Account Disabled'),
|
||||||
message=gettext_lazy(
|
message=gettext_lazy(
|
||||||
'Your Discord account was disabled automatically '
|
'Your Discord account was disabled automatically '
|
||||||
'by Auth. If you think this was a mistake, '
|
'by Auth. If you think this was a mistake, '
|
||||||
@ -235,18 +235,18 @@ class DiscordUser(models.Model):
|
|||||||
else:
|
else:
|
||||||
logger.debug('Account for user %s was already deleted.', _user)
|
logger.debug('Account for user %s was already deleted.', _user)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'Failed to remove user %s from the Discord server', _user
|
'Failed to remove user %s from the Discord server', _user
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
||||||
if handle_api_exceptions:
|
if handle_api_exceptions:
|
||||||
logger.exception(
|
logger.exception(
|
||||||
'Failed to remove user %s from Discord server: %s',self.user, ex
|
'Failed to remove user %s from Discord server: %s',self.user, ex
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
raise ex
|
raise ex
|
||||||
|
|||||||
@ -29,11 +29,11 @@ BULK_TASK_PRIORITY = 6
|
|||||||
)
|
)
|
||||||
def update_groups(self, user_pk: int, state_name: str = None) -> None:
|
def update_groups(self, user_pk: int, state_name: str = None) -> None:
|
||||||
"""Update roles on Discord for given user according to his current groups
|
"""Update roles on Discord for given user according to his current groups
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- user_pk: PK of given user
|
- user_pk: PK of given user
|
||||||
- state_name: optional state name to be used
|
- state_name: optional state name to be used
|
||||||
"""
|
"""
|
||||||
_task_perform_user_action(self, user_pk, 'update_groups', state_name=state_name)
|
_task_perform_user_action(self, user_pk, 'update_groups', state_name=state_name)
|
||||||
|
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ def update_groups(self, user_pk: int, state_name: str = None) -> None:
|
|||||||
)
|
)
|
||||||
def update_nickname(self, user_pk: int, nickname: str = None) -> None:
|
def update_nickname(self, user_pk: int, nickname: str = None) -> None:
|
||||||
"""Set nickname on Discord for given user to his main character name
|
"""Set nickname on Discord for given user to his main character name
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- user_pk: PK of given user
|
- user_pk: PK of given user
|
||||||
- nickname: optional nickname to be used instead of user's main
|
- nickname: optional nickname to be used instead of user's main
|
||||||
@ -55,7 +55,7 @@ def update_nickname(self, user_pk: int, nickname: str = None) -> None:
|
|||||||
)
|
)
|
||||||
def update_username(self, user_pk: int) -> None:
|
def update_username(self, user_pk: int) -> None:
|
||||||
"""Update locally stored Discord username from Discord server for given user
|
"""Update locally stored Discord username from Discord server for given user
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- user_pk: PK of given user
|
- user_pk: PK of given user
|
||||||
"""
|
"""
|
||||||
@ -67,7 +67,7 @@ def update_username(self, user_pk: int) -> None:
|
|||||||
)
|
)
|
||||||
def delete_user(self, user_pk: int, notify_user: bool = False) -> None:
|
def delete_user(self, user_pk: int, notify_user: bool = False) -> None:
|
||||||
"""Delete Discord user
|
"""Delete Discord user
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- user_pk: PK of given user
|
- user_pk: PK of given user
|
||||||
"""
|
"""
|
||||||
@ -77,13 +77,13 @@ def delete_user(self, user_pk: int, notify_user: bool = False) -> None:
|
|||||||
def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None:
|
def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None:
|
||||||
"""perform a user related action incl. managing all exceptions"""
|
"""perform a user related action incl. managing all exceptions"""
|
||||||
logger.debug("Starting %s for user with pk %s", method, user_pk)
|
logger.debug("Starting %s for user with pk %s", method, user_pk)
|
||||||
user = User.objects.get(pk=user_pk)
|
user = User.objects.get(pk=user_pk)
|
||||||
# logger.debug("user %s has state %s", user, user.profile.state)
|
# logger.debug("user %s has state %s", user, user.profile.state)
|
||||||
if DiscordUser.objects.user_has_account(user):
|
if DiscordUser.objects.user_has_account(user):
|
||||||
logger.info("Running %s for user %s", method, user)
|
logger.info("Running %s for user %s", method, user)
|
||||||
try:
|
try:
|
||||||
success = getattr(user.discord, method)(**kwargs)
|
success = getattr(user.discord, method)(**kwargs)
|
||||||
|
|
||||||
except DiscordApiBackoff as bo:
|
except DiscordApiBackoff as bo:
|
||||||
logger.info(
|
logger.info(
|
||||||
"API back off for %s wth user %s due to %r, retrying in %s seconds",
|
"API back off for %s wth user %s due to %r, retrying in %s seconds",
|
||||||
@ -92,26 +92,26 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
|
|||||||
bo,
|
bo,
|
||||||
bo.retry_after_seconds
|
bo.retry_after_seconds
|
||||||
)
|
)
|
||||||
raise self.retry(countdown=bo.retry_after_seconds)
|
raise self.retry(countdown=bo.retry_after_seconds)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ValueError(f'{method} not a valid method for DiscordUser')
|
raise ValueError(f'{method} not a valid method for DiscordUser')
|
||||||
|
|
||||||
except (HTTPError, ConnectionError):
|
except (HTTPError, ConnectionError):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'%s failed for user %s, retrying in %d secs',
|
'%s failed for user %s, retrying in %d secs',
|
||||||
method,
|
method,
|
||||||
user,
|
user,
|
||||||
DISCORD_TASKS_RETRY_PAUSE,
|
DISCORD_TASKS_RETRY_PAUSE,
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
|
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
|
||||||
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
|
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
'%s failed for user %s after max retries',
|
'%s failed for user %s after max retries',
|
||||||
method,
|
method,
|
||||||
user,
|
user,
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -120,8 +120,8 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
|
|||||||
method,
|
method,
|
||||||
user,
|
user,
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if success is None and method != 'delete_user':
|
if success is None and method != 'delete_user':
|
||||||
delete_user.delay(user.pk, notify_user=True)
|
delete_user.delay(user.pk, notify_user=True)
|
||||||
@ -134,14 +134,14 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
|
|||||||
|
|
||||||
@shared_task(name='discord.update_all_groups')
|
@shared_task(name='discord.update_all_groups')
|
||||||
def update_all_groups() -> None:
|
def update_all_groups() -> None:
|
||||||
"""Update roles for all known users with a Discord account."""
|
"""Update roles for all known users with a Discord account."""
|
||||||
discord_users_qs = DiscordUser.objects.all()
|
discord_users_qs = DiscordUser.objects.all()
|
||||||
_bulk_update_groups_for_users(discord_users_qs)
|
_bulk_update_groups_for_users(discord_users_qs)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name='discord.update_groups_bulk')
|
@shared_task(name='discord.update_groups_bulk')
|
||||||
def update_groups_bulk(user_pks: list) -> None:
|
def update_groups_bulk(user_pks: list) -> None:
|
||||||
"""Update roles for list of users with a Discord account in bulk."""
|
"""Update roles for list of users with a Discord account in bulk."""
|
||||||
discord_users_qs = DiscordUser.objects\
|
discord_users_qs = DiscordUser.objects\
|
||||||
.filter(user__pk__in=user_pks)\
|
.filter(user__pk__in=user_pks)\
|
||||||
.select_related()
|
.select_related()
|
||||||
@ -155,7 +155,7 @@ def _bulk_update_groups_for_users(discord_users_qs: QuerySet) -> None:
|
|||||||
update_groups_chain = list()
|
update_groups_chain = list()
|
||||||
for discord_user in discord_users_qs:
|
for discord_user in discord_users_qs:
|
||||||
update_groups_chain.append(update_groups.si(discord_user.user.pk))
|
update_groups_chain.append(update_groups.si(discord_user.user.pk))
|
||||||
|
|
||||||
chain(update_groups_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
chain(update_groups_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
||||||
|
|
||||||
|
|
||||||
@ -164,11 +164,11 @@ def update_all_nicknames() -> None:
|
|||||||
"""Update nicknames for all known users with a Discord account."""
|
"""Update nicknames for all known users with a Discord account."""
|
||||||
discord_users_qs = DiscordUser.objects.all()
|
discord_users_qs = DiscordUser.objects.all()
|
||||||
_bulk_update_nicknames_for_users(discord_users_qs)
|
_bulk_update_nicknames_for_users(discord_users_qs)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name='discord.update_nicknames_bulk')
|
@shared_task(name='discord.update_nicknames_bulk')
|
||||||
def update_nicknames_bulk(user_pks: list) -> None:
|
def update_nicknames_bulk(user_pks: list) -> None:
|
||||||
"""Update nicknames for list of users with a Discord account in bulk."""
|
"""Update nicknames for list of users with a Discord account in bulk."""
|
||||||
discord_users_qs = DiscordUser.objects\
|
discord_users_qs = DiscordUser.objects\
|
||||||
.filter(user__pk__in=user_pks)\
|
.filter(user__pk__in=user_pks)\
|
||||||
.select_related()
|
.select_related()
|
||||||
@ -177,27 +177,27 @@ def update_nicknames_bulk(user_pks: list) -> None:
|
|||||||
|
|
||||||
def _bulk_update_nicknames_for_users(discord_users_qs: QuerySet) -> None:
|
def _bulk_update_nicknames_for_users(discord_users_qs: QuerySet) -> None:
|
||||||
logger.info(
|
logger.info(
|
||||||
"Starting to bulk update discord nicknames for %d users",
|
"Starting to bulk update discord nicknames for %d users",
|
||||||
discord_users_qs.count()
|
discord_users_qs.count()
|
||||||
)
|
)
|
||||||
update_nicknames_chain = list()
|
update_nicknames_chain = list()
|
||||||
for discord_user in discord_users_qs:
|
for discord_user in discord_users_qs:
|
||||||
update_nicknames_chain.append(update_nickname.si(discord_user.user.pk))
|
update_nicknames_chain.append(update_nickname.si(discord_user.user.pk))
|
||||||
|
|
||||||
chain(update_nicknames_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
chain(update_nicknames_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
||||||
|
|
||||||
|
|
||||||
def _task_perform_users_action(self, method: str, **kwargs) -> Any:
|
def _task_perform_users_action(self, method: str, **kwargs) -> Any:
|
||||||
"""Perform an action that concerns a group of users or the whole server
|
"""Perform an action that concerns a group of users or the whole server
|
||||||
and that hits the API
|
and that hits the API
|
||||||
"""
|
"""
|
||||||
result = None
|
result = None
|
||||||
try:
|
try:
|
||||||
result = getattr(DiscordUser.objects, method)(**kwargs)
|
result = getattr(DiscordUser.objects, method)(**kwargs)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ValueError(f'{method} not a valid method for DiscordUser.objects')
|
raise ValueError(f'{method} not a valid method for DiscordUser.objects')
|
||||||
|
|
||||||
except DiscordApiBackoff as bo:
|
except DiscordApiBackoff as bo:
|
||||||
logger.info(
|
logger.info(
|
||||||
"API back off for %s due to %r, retrying in %s seconds",
|
"API back off for %s due to %r, retrying in %s seconds",
|
||||||
@ -205,23 +205,23 @@ def _task_perform_users_action(self, method: str, **kwargs) -> Any:
|
|||||||
bo,
|
bo,
|
||||||
bo.retry_after_seconds
|
bo.retry_after_seconds
|
||||||
)
|
)
|
||||||
raise self.retry(countdown=bo.retry_after_seconds)
|
raise self.retry(countdown=bo.retry_after_seconds)
|
||||||
|
|
||||||
except (HTTPError, ConnectionError):
|
except (HTTPError, ConnectionError):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'%s failed, retrying in %d secs',
|
'%s failed, retrying in %d secs',
|
||||||
method,
|
method,
|
||||||
DISCORD_TASKS_RETRY_PAUSE,
|
DISCORD_TASKS_RETRY_PAUSE,
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
|
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
|
||||||
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
|
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
|
||||||
else:
|
else:
|
||||||
logger.error('%s failed after max retries', method, exc_info=True)
|
logger.error('%s failed after max retries', method, exc_info=True)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error('%s failed due to unexpected exception', method, exc_info=True)
|
logger.error('%s failed due to unexpected exception', method, exc_info=True)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@ -235,17 +235,17 @@ def update_servername(self) -> None:
|
|||||||
|
|
||||||
@shared_task(name='discord.update_all_usernames')
|
@shared_task(name='discord.update_all_usernames')
|
||||||
def update_all_usernames() -> None:
|
def update_all_usernames() -> None:
|
||||||
"""Update all usernames for all known users with a Discord account.
|
"""Update all usernames for all known users with a Discord account.
|
||||||
Also updates the server name
|
Also updates the server name
|
||||||
"""
|
"""
|
||||||
update_servername.delay()
|
update_servername.delay()
|
||||||
discord_users_qs = DiscordUser.objects.all()
|
discord_users_qs = DiscordUser.objects.all()
|
||||||
_bulk_update_usernames_for_users(discord_users_qs)
|
_bulk_update_usernames_for_users(discord_users_qs)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name='discord.update_usernames_bulk')
|
@shared_task(name='discord.update_usernames_bulk')
|
||||||
def update_usernames_bulk(user_pks: list) -> None:
|
def update_usernames_bulk(user_pks: list) -> None:
|
||||||
"""Update usernames for list of users with a Discord account in bulk."""
|
"""Update usernames for list of users with a Discord account in bulk."""
|
||||||
discord_users_qs = DiscordUser.objects\
|
discord_users_qs = DiscordUser.objects\
|
||||||
.filter(user__pk__in=user_pks)\
|
.filter(user__pk__in=user_pks)\
|
||||||
.select_related()
|
.select_related()
|
||||||
@ -254,13 +254,13 @@ def update_usernames_bulk(user_pks: list) -> None:
|
|||||||
|
|
||||||
def _bulk_update_usernames_for_users(discord_users_qs: QuerySet) -> None:
|
def _bulk_update_usernames_for_users(discord_users_qs: QuerySet) -> None:
|
||||||
logger.info(
|
logger.info(
|
||||||
"Starting to bulk update discord usernames for %d users",
|
"Starting to bulk update discord usernames for %d users",
|
||||||
discord_users_qs.count()
|
discord_users_qs.count()
|
||||||
)
|
)
|
||||||
update_usernames_chain = list()
|
update_usernames_chain = list()
|
||||||
for discord_user in discord_users_qs:
|
for discord_user in discord_users_qs:
|
||||||
update_usernames_chain.append(update_username.si(discord_user.user.pk))
|
update_usernames_chain.append(update_username.si(discord_user.user.pk))
|
||||||
|
|
||||||
chain(update_usernames_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
chain(update_usernames_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
||||||
|
|
||||||
|
|
||||||
@ -277,5 +277,5 @@ def update_all() -> None:
|
|||||||
update_all_chain.append(update_username.si(discord_user.user.pk))
|
update_all_chain.append(update_username.si(discord_user.user.pk))
|
||||||
if DISCORD_SYNC_NAMES:
|
if DISCORD_SYNC_NAMES:
|
||||||
update_all_chain.append(update_nickname.si(discord_user.user.pk))
|
update_all_chain.append(update_nickname.si(discord_user.user.pk))
|
||||||
|
|
||||||
chain(update_all_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
chain(update_all_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
||||||
|
|||||||
@ -5,14 +5,14 @@ from ..discord_client.tests import ( # noqa
|
|||||||
TEST_USER_ID,
|
TEST_USER_ID,
|
||||||
TEST_USER_NAME,
|
TEST_USER_NAME,
|
||||||
TEST_USER_DISCRIMINATOR,
|
TEST_USER_DISCRIMINATOR,
|
||||||
create_role,
|
create_role,
|
||||||
ROLE_ALPHA,
|
ROLE_ALPHA,
|
||||||
ROLE_BRAVO,
|
ROLE_BRAVO,
|
||||||
ROLE_CHARLIE,
|
ROLE_CHARLIE,
|
||||||
ROLE_MIKE,
|
ROLE_MIKE,
|
||||||
ALL_ROLES,
|
ALL_ROLES,
|
||||||
create_user_info
|
create_user_info
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_AUTH_GROUP = 'Member'
|
DEFAULT_AUTH_GROUP = 'Member'
|
||||||
MODULE_PATH = 'allianceauth.services.modules.discord'
|
MODULE_PATH = 'allianceauth.services.modules.discord'
|
||||||
|
|||||||
@ -53,21 +53,21 @@ def run_many_updates(runs):
|
|||||||
logger.info('Starting piloting_tasks for %d runs', runs)
|
logger.info('Starting piloting_tasks for %d runs', runs)
|
||||||
users = list()
|
users = list()
|
||||||
all_groups = Group.objects.all()
|
all_groups = Group.objects.all()
|
||||||
for i in range(runs):
|
for i in range(runs):
|
||||||
if not users:
|
if not users:
|
||||||
users = list(User.objects.filter(discord__isnull=False))
|
users = list(User.objects.filter(discord__isnull=False))
|
||||||
user = users.pop()
|
user = users.pop()
|
||||||
logger.info('%d/%d: Starting run with user %s', i + 1, runs, user)
|
logger.info('%d/%d: Starting run with user %s', i + 1, runs, user)
|
||||||
# force change of nick
|
# force change of nick
|
||||||
new_nick = f'Testnick {uuid1().hex}'[:32]
|
new_nick = f'Testnick {uuid1().hex}'[:32]
|
||||||
logger.info(
|
logger.info(
|
||||||
'%d/%d: Changing nickname of %s to "%s"', i + 1, runs, user, new_nick
|
'%d/%d: Changing nickname of %s to "%s"', i + 1, runs, user, new_nick
|
||||||
)
|
)
|
||||||
user.profile.main_character.character_name = new_nick
|
user.profile.main_character.character_name = new_nick
|
||||||
user.profile.main_character.save()
|
user.profile.main_character.save()
|
||||||
|
|
||||||
# force change of groups
|
# force change of groups
|
||||||
user_groups = user.groups.all()
|
user_groups = user.groups.all()
|
||||||
user.groups.remove(random.choice(user_groups))
|
user.groups.remove(random.choice(user_groups))
|
||||||
while True:
|
while True:
|
||||||
new_group = random.choice(all_groups)
|
new_group = random.choice(all_groups)
|
||||||
|
|||||||
@ -9,9 +9,9 @@ from allianceauth.eveonline.models import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from ....admin import (
|
from ....admin import (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
user_main_organization,
|
user_main_organization,
|
||||||
ServicesUserAdmin,
|
ServicesUserAdmin,
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter
|
MainAllianceFilter
|
||||||
@ -31,7 +31,7 @@ class TestDataMixin(TestCase):
|
|||||||
EveAllianceInfo.objects.all().delete()
|
EveAllianceInfo.objects.all().delete()
|
||||||
User.objects.all().delete()
|
User.objects.all().delete()
|
||||||
DiscordUser.objects.all().delete()
|
DiscordUser.objects.all().delete()
|
||||||
|
|
||||||
# user 1 - corp and alliance, normal user
|
# user 1 - corp and alliance, normal user
|
||||||
cls.character_1 = EveCharacter.objects.create(
|
cls.character_1 = EveCharacter.objects.create(
|
||||||
character_id=1001,
|
character_id=1001,
|
||||||
@ -56,16 +56,16 @@ class TestDataMixin(TestCase):
|
|||||||
alliance = EveAllianceInfo.objects.create(
|
alliance = EveAllianceInfo.objects.create(
|
||||||
alliance_id=3001,
|
alliance_id=3001,
|
||||||
alliance_name='Wayne Enterprises',
|
alliance_name='Wayne Enterprises',
|
||||||
alliance_ticker='WE',
|
alliance_ticker='WE',
|
||||||
executor_corp_id=2001
|
executor_corp_id=2001
|
||||||
)
|
)
|
||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2001,
|
corporation_id=2001,
|
||||||
corporation_name='Wayne Technologies',
|
corporation_name='Wayne Technologies',
|
||||||
corporation_ticker='WT',
|
corporation_ticker='WT',
|
||||||
member_count=42,
|
member_count=42,
|
||||||
alliance=alliance
|
alliance=alliance
|
||||||
)
|
)
|
||||||
cls.user_1 = User.objects.create_user(
|
cls.user_1 = User.objects.create_user(
|
||||||
cls.character_1.character_name.replace(' ', '_'),
|
cls.character_1.character_name.replace(' ', '_'),
|
||||||
'abc@example.com',
|
'abc@example.com',
|
||||||
@ -103,7 +103,7 @@ class TestDataMixin(TestCase):
|
|||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2002,
|
corporation_id=2002,
|
||||||
corporation_name='Daily Plane',
|
corporation_name='Daily Plane',
|
||||||
corporation_ticker='DP',
|
corporation_ticker='DP',
|
||||||
member_count=99,
|
member_count=99,
|
||||||
alliance=None
|
alliance=None
|
||||||
)
|
)
|
||||||
@ -123,7 +123,7 @@ class TestDataMixin(TestCase):
|
|||||||
user=cls.user_2,
|
user=cls.user_2,
|
||||||
uid=1002
|
uid=1002
|
||||||
)
|
)
|
||||||
|
|
||||||
# user 3 - no main, no group, superuser
|
# user 3 - no main, no group, superuser
|
||||||
cls.character_3 = EveCharacter.objects.create(
|
cls.character_3 = EveCharacter.objects.create(
|
||||||
character_id=1101,
|
character_id=1101,
|
||||||
@ -136,7 +136,7 @@ class TestDataMixin(TestCase):
|
|||||||
EveCorporationInfo.objects.create(
|
EveCorporationInfo.objects.create(
|
||||||
corporation_id=2101,
|
corporation_id=2101,
|
||||||
corporation_name='Lex Corp',
|
corporation_name='Lex Corp',
|
||||||
corporation_ticker='LC',
|
corporation_ticker='LC',
|
||||||
member_count=666,
|
member_count=666,
|
||||||
alliance=None
|
alliance=None
|
||||||
)
|
)
|
||||||
@ -160,13 +160,13 @@ class TestDataMixin(TestCase):
|
|||||||
user=cls.user_3,
|
user=cls.user_3,
|
||||||
uid=1003
|
uid=1003
|
||||||
)
|
)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.factory = RequestFactory()
|
self.factory = RequestFactory()
|
||||||
self.modeladmin = DiscordUserAdmin(
|
self.modeladmin = DiscordUserAdmin(
|
||||||
model=DiscordUser, admin_site=AdminSite()
|
model=DiscordUser, admin_site=AdminSite()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestColumnRendering(TestDataMixin, TestCase):
|
class TestColumnRendering(TestDataMixin, TestCase):
|
||||||
|
|
||||||
@ -230,12 +230,12 @@ class TestColumnRendering(TestDataMixin, TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestFilters(TestDataMixin, TestCase):
|
class TestFilters(TestDataMixin, TestCase):
|
||||||
|
|
||||||
def test_filter_main_corporations(self):
|
def test_filter_main_corporations(self):
|
||||||
|
|
||||||
class DiscordUserAdminTest(ServicesUserAdmin):
|
class DiscordUserAdminTest(ServicesUserAdmin):
|
||||||
list_filter = (MainCorporationsFilter,)
|
list_filter = (MainCorporationsFilter,)
|
||||||
|
|
||||||
my_modeladmin = DiscordUserAdminTest(DiscordUser, AdminSite())
|
my_modeladmin = DiscordUserAdminTest(DiscordUser, AdminSite())
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
# Make sure the lookups are correct
|
||||||
@ -244,7 +244,7 @@ class TestFilters(TestDataMixin, TestCase):
|
|||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
filters = changelist.get_filters(request)
|
filters = changelist.get_filters(request)
|
||||||
filterspec = filters[0][0]
|
filterspec = filters[0][0]
|
||||||
expected = [
|
expected = [
|
||||||
(2002, 'Daily Planet'),
|
(2002, 'Daily Planet'),
|
||||||
(2001, 'Wayne Technologies'),
|
(2001, 'Wayne Technologies'),
|
||||||
]
|
]
|
||||||
@ -254,19 +254,19 @@ class TestFilters(TestDataMixin, TestCase):
|
|||||||
request = self.factory.get(
|
request = self.factory.get(
|
||||||
'/', {'main_corporation_id__exact': self.character_1.corporation_id}
|
'/', {'main_corporation_id__exact': self.character_1.corporation_id}
|
||||||
)
|
)
|
||||||
request.user = self.user_1
|
request.user = self.user_1
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
queryset = changelist.get_queryset(request)
|
queryset = changelist.get_queryset(request)
|
||||||
expected = [self.user_1.discord]
|
expected = [self.user_1.discord]
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
self.assertSetEqual(set(queryset), set(expected))
|
||||||
|
|
||||||
def test_filter_main_alliances(self):
|
def test_filter_main_alliances(self):
|
||||||
|
|
||||||
class DiscordUserAdminTest(ServicesUserAdmin):
|
class DiscordUserAdminTest(ServicesUserAdmin):
|
||||||
list_filter = (MainAllianceFilter,)
|
list_filter = (MainAllianceFilter,)
|
||||||
|
|
||||||
my_modeladmin = DiscordUserAdminTest(DiscordUser, AdminSite())
|
my_modeladmin = DiscordUserAdminTest(DiscordUser, AdminSite())
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
# Make sure the lookups are correct
|
||||||
request = self.factory.get('/')
|
request = self.factory.get('/')
|
||||||
request.user = self.user_1
|
request.user = self.user_1
|
||||||
@ -282,7 +282,7 @@ class TestFilters(TestDataMixin, TestCase):
|
|||||||
request = self.factory.get(
|
request = self.factory.get(
|
||||||
'/', {'main_alliance_id__exact': self.character_1.alliance_id}
|
'/', {'main_alliance_id__exact': self.character_1.alliance_id}
|
||||||
)
|
)
|
||||||
request.user = self.user_1
|
request.user = self.user_1
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
changelist = my_modeladmin.get_changelist_instance(request)
|
||||||
queryset = changelist.get_queryset(request)
|
queryset = changelist.get_queryset(request)
|
||||||
expected = [self.user_1.discord]
|
expected = [self.user_1.discord]
|
||||||
|
|||||||
@ -19,11 +19,11 @@ logger = set_logger_to_file(MODULE_PATH + '.auth_hooks', __file__)
|
|||||||
@override_settings(CELERY_ALWAYS_EAGER=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
class TestDiscordService(TestCase):
|
class TestDiscordService(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.member = AuthUtils.create_member(TEST_USER_NAME)
|
self.member = AuthUtils.create_member(TEST_USER_NAME)
|
||||||
DiscordUser.objects.create(
|
DiscordUser.objects.create(
|
||||||
user=self.member,
|
user=self.member,
|
||||||
uid=TEST_USER_ID,
|
uid=TEST_USER_ID,
|
||||||
username=TEST_USER_NAME,
|
username=TEST_USER_NAME,
|
||||||
discriminator='1234'
|
discriminator='1234'
|
||||||
)
|
)
|
||||||
@ -34,33 +34,33 @@ class TestDiscordService(TestCase):
|
|||||||
Notification.objects.all().delete()
|
Notification.objects.all().delete()
|
||||||
|
|
||||||
def test_service_enabled(self):
|
def test_service_enabled(self):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
self.assertTrue(service.service_active_for_user(self.member))
|
self.assertTrue(service.service_active_for_user(self.member))
|
||||||
self.assertFalse(service.service_active_for_user(self.none_member))
|
self.assertFalse(service.service_active_for_user(self.none_member))
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.tasks.update_all_groups')
|
@patch(MODULE_PATH + '.tasks.update_all_groups')
|
||||||
def test_update_all_groups(self, mock_update_all_groups):
|
def test_update_all_groups(self, mock_update_all_groups):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.update_all_groups()
|
service.update_all_groups()
|
||||||
self.assertTrue(mock_update_all_groups.delay.called)
|
self.assertTrue(mock_update_all_groups.delay.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.tasks.update_groups_bulk')
|
@patch(MODULE_PATH + '.tasks.update_groups_bulk')
|
||||||
def test_update_groups_bulk(self, mock_update_groups_bulk):
|
def test_update_groups_bulk(self, mock_update_groups_bulk):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.update_groups_bulk([self.member])
|
service.update_groups_bulk([self.member])
|
||||||
self.assertTrue(mock_update_groups_bulk.delay.called)
|
self.assertTrue(mock_update_groups_bulk.delay.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.tasks.update_groups')
|
@patch(MODULE_PATH + '.tasks.update_groups')
|
||||||
def test_update_groups_for_member(self, mock_update_groups):
|
def test_update_groups_for_member(self, mock_update_groups):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.update_groups(self.member)
|
service.update_groups(self.member)
|
||||||
self.assertTrue(mock_update_groups.apply_async.called)
|
self.assertTrue(mock_update_groups.apply_async.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.tasks.update_groups')
|
@patch(MODULE_PATH + '.tasks.update_groups')
|
||||||
def test_update_groups_for_none_member(self, mock_update_groups):
|
def test_update_groups_for_none_member(self, mock_update_groups):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.update_groups(self.none_member)
|
service.update_groups(self.none_member)
|
||||||
self.assertFalse(mock_update_groups.apply_async.called)
|
self.assertFalse(mock_update_groups.apply_async.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.models.notify')
|
@patch(MODULE_PATH + '.models.notify')
|
||||||
@patch(MODULE_PATH + '.tasks.DiscordUser')
|
@patch(MODULE_PATH + '.tasks.DiscordUser')
|
||||||
@ -69,52 +69,52 @@ class TestDiscordService(TestCase):
|
|||||||
self, mock_DiscordClient, mock_DiscordUser, mock_notify
|
self, mock_DiscordClient, mock_DiscordUser, mock_notify
|
||||||
):
|
):
|
||||||
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
||||||
|
|
||||||
# Test member is not deleted
|
# Test member is not deleted
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.validate_user(self.member)
|
service.validate_user(self.member)
|
||||||
self.assertTrue(DiscordUser.objects.filter(user=self.member).exists())
|
self.assertTrue(DiscordUser.objects.filter(user=self.member).exists())
|
||||||
|
|
||||||
# Test none member is deleted
|
# Test none member is deleted
|
||||||
DiscordUser.objects.create(user=self.none_member, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.none_member, uid=TEST_USER_ID)
|
||||||
service.validate_user(self.none_member)
|
service.validate_user(self.none_member)
|
||||||
self.assertFalse(DiscordUser.objects.filter(user=self.none_member).exists())
|
self.assertFalse(DiscordUser.objects.filter(user=self.none_member).exists())
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.tasks.update_nickname')
|
@patch(MODULE_PATH + '.tasks.update_nickname')
|
||||||
def test_sync_nickname(self, mock_update_nickname):
|
def test_sync_nickname(self, mock_update_nickname):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.sync_nickname(self.member)
|
service.sync_nickname(self.member)
|
||||||
self.assertTrue(mock_update_nickname.apply_async.called)
|
self.assertTrue(mock_update_nickname.apply_async.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.tasks.update_nicknames_bulk')
|
@patch(MODULE_PATH + '.tasks.update_nicknames_bulk')
|
||||||
def test_sync_nicknames_bulk(self, mock_update_nicknames_bulk):
|
def test_sync_nicknames_bulk(self, mock_update_nicknames_bulk):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.sync_nicknames_bulk([self.member])
|
service.sync_nicknames_bulk([self.member])
|
||||||
self.assertTrue(mock_update_nicknames_bulk.delay.called)
|
self.assertTrue(mock_update_nicknames_bulk.delay.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
def test_delete_user_is_member(self, mock_DiscordClient):
|
def test_delete_user_is_member(self, mock_DiscordClient):
|
||||||
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
||||||
|
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.delete_user(self.member, notify_user=True)
|
service.delete_user(self.member, notify_user=True)
|
||||||
|
|
||||||
self.assertTrue(mock_DiscordClient.return_value.remove_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.remove_guild_member.called)
|
||||||
self.assertFalse(DiscordUser.objects.filter(user=self.member).exists())
|
self.assertFalse(DiscordUser.objects.filter(user=self.member).exists())
|
||||||
self.assertTrue(Notification.objects.filter(user=self.member).exists())
|
self.assertTrue(Notification.objects.filter(user=self.member).exists())
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
def test_delete_user_is_not_member(self, mock_DiscordClient):
|
def test_delete_user_is_not_member(self, mock_DiscordClient):
|
||||||
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
||||||
|
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.delete_user(self.none_member)
|
service.delete_user(self.none_member)
|
||||||
|
|
||||||
self.assertFalse(mock_DiscordClient.return_value.remove_guild_member.called)
|
self.assertFalse(mock_DiscordClient.return_value.remove_guild_member.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
def test_render_services_ctrl_with_username(self, mock_DiscordClient):
|
def test_render_services_ctrl_with_username(self, mock_DiscordClient):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
request = self.factory.get('/services/')
|
request = self.factory.get('/services/')
|
||||||
request.user = self.member
|
request.user = self.member
|
||||||
|
|
||||||
|
|||||||
@ -26,11 +26,11 @@ from allianceauth.tests.auth_utils import AuthUtils
|
|||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
TEST_GUILD_ID,
|
TEST_GUILD_ID,
|
||||||
TEST_USER_NAME,
|
TEST_USER_NAME,
|
||||||
TEST_USER_ID,
|
TEST_USER_ID,
|
||||||
TEST_USER_DISCRIMINATOR,
|
TEST_USER_DISCRIMINATOR,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
add_permissions_to_members,
|
add_permissions_to_members,
|
||||||
ROLE_ALPHA,
|
ROLE_ALPHA,
|
||||||
@ -75,11 +75,11 @@ guild_member_request = DiscordRequest(
|
|||||||
add_guild_member_request = DiscordRequest(
|
add_guild_member_request = DiscordRequest(
|
||||||
method='PUT',
|
method='PUT',
|
||||||
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/{TEST_USER_ID}'
|
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/{TEST_USER_ID}'
|
||||||
)
|
)
|
||||||
modify_guild_member_request = DiscordRequest(
|
modify_guild_member_request = DiscordRequest(
|
||||||
method='PATCH',
|
method='PATCH',
|
||||||
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/{TEST_USER_ID}'
|
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/{TEST_USER_ID}'
|
||||||
)
|
)
|
||||||
remove_guild_member_request = DiscordRequest(
|
remove_guild_member_request = DiscordRequest(
|
||||||
method='DELETE',
|
method='DELETE',
|
||||||
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/{TEST_USER_ID}'
|
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/{TEST_USER_ID}'
|
||||||
@ -93,7 +93,7 @@ def clear_cache():
|
|||||||
logger.info('Cache flushed')
|
logger.info('Cache flushed')
|
||||||
|
|
||||||
|
|
||||||
def reset_testdata():
|
def reset_testdata():
|
||||||
AuthUtils.disconnect_signals()
|
AuthUtils.disconnect_signals()
|
||||||
Group.objects.all().delete()
|
Group.objects.all().delete()
|
||||||
User.objects.all().delete()
|
User.objects.all().delete()
|
||||||
@ -112,15 +112,15 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.maxDiff = None
|
cls.maxDiff = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""All tests: Given a user with member state,
|
"""All tests: Given a user with member state,
|
||||||
service permission and active Discord account
|
service permission and active Discord account
|
||||||
"""
|
"""
|
||||||
clear_cache()
|
clear_cache()
|
||||||
reset_testdata()
|
reset_testdata()
|
||||||
self.group_charlie = Group.objects.create(name='charlie')
|
self.group_charlie = Group.objects.create(name='charlie')
|
||||||
|
|
||||||
# States
|
# States
|
||||||
self.member_state = AuthUtils.get_member_state()
|
self.member_state = AuthUtils.get_member_state()
|
||||||
self.guest_state = AuthUtils.get_guest_state()
|
self.guest_state = AuthUtils.get_guest_state()
|
||||||
@ -132,64 +132,64 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
# Test user
|
# Test user
|
||||||
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
self.main = AuthUtils.add_main_character_2(
|
self.main = AuthUtils.add_main_character_2(
|
||||||
self.user,
|
self.user,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='test_corp',
|
corp_name='test_corp',
|
||||||
corp_ticker='TEST',
|
corp_ticker='TEST',
|
||||||
disconnect_signals=True
|
disconnect_signals=True
|
||||||
)
|
)
|
||||||
self.member_state.member_characters.add(self.main)
|
self.member_state.member_characters.add(self.main)
|
||||||
|
|
||||||
# verify user is a member and has an account
|
# verify user is a member and has an account
|
||||||
self.user = User.objects.get(pk=self.user.pk)
|
self.user = User.objects.get(pk=self.user.pk)
|
||||||
self.assertEqual(self.user.profile.state, self.member_state)
|
self.assertEqual(self.user.profile.state, self.member_state)
|
||||||
|
|
||||||
self.discord_user = DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
self.discord_user = DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
def test_when_name_of_main_changes_then_discord_nick_is_updated(
|
def test_when_name_of_main_changes_then_discord_nick_is_updated(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# changing nick to trigger signals
|
# changing nick to trigger signals
|
||||||
new_nick = f'Testnick {uuid1().hex}'[:32]
|
new_nick = f'Testnick {uuid1().hex}'[:32]
|
||||||
self.user.profile.main_character.character_name = new_nick
|
self.user.profile.main_character.character_name = new_nick
|
||||||
self.user.profile.main_character.save()
|
self.user.profile.main_character.save()
|
||||||
|
|
||||||
# verify Discord nick was updates
|
# verify Discord nick was updates
|
||||||
nick_updated = False
|
nick_updated = False
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
my_request = DiscordRequest(r.method, r.url)
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
if my_request == modify_guild_member_request and "nick" in r.json():
|
if my_request == modify_guild_member_request and "nick" in r.json():
|
||||||
nick_updated = True
|
nick_updated = True
|
||||||
self.assertEqual(r.json()["nick"], new_nick)
|
self.assertEqual(r.json()["nick"], new_nick)
|
||||||
|
|
||||||
self.assertTrue(nick_updated)
|
self.assertTrue(nick_updated)
|
||||||
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
def test_when_name_of_main_changes_and_user_deleted_then_account_is_deleted(
|
def test_when_name_of_main_changes_and_user_deleted_then_account_is_deleted(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
requests_mocker.patch(
|
requests_mocker.patch(
|
||||||
modify_guild_member_request.url, status_code=404, json={'code': 10007}
|
modify_guild_member_request.url, status_code=404, json={'code': 10007}
|
||||||
)
|
)
|
||||||
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# changing nick to trigger signals
|
# changing nick to trigger signals
|
||||||
new_nick = f'Testnick {uuid1().hex}'[:32]
|
new_nick = f'Testnick {uuid1().hex}'[:32]
|
||||||
self.user.profile.main_character.character_name = new_nick
|
self.user.profile.main_character.character_name = new_nick
|
||||||
self.user.profile.main_character.save()
|
self.user.profile.main_character.save()
|
||||||
|
|
||||||
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
def test_when_name_of_main_changes_and_and_rate_limited_then_dont_call_api(
|
def test_when_name_of_main_changes_and_and_rate_limited_then_dont_call_api(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# exhausting rate limit
|
# exhausting rate limit
|
||||||
client = DiscordUser.objects._bot_client()
|
client = DiscordUser.objects._bot_client()
|
||||||
client._redis.set(
|
client._redis.set(
|
||||||
@ -197,7 +197,7 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
value=0,
|
value=0,
|
||||||
px=2000
|
px=2000
|
||||||
)
|
)
|
||||||
|
|
||||||
# changing nick to trigger signals
|
# changing nick to trigger signals
|
||||||
new_nick = f'Testnick {uuid1().hex}'[:32]
|
new_nick = f'Testnick {uuid1().hex}'[:32]
|
||||||
self.user.profile.main_character.character_name = new_nick
|
self.user.profile.main_character.character_name = new_nick
|
||||||
@ -207,55 +207,55 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
requests_made = [
|
requests_made = [
|
||||||
DiscordRequest(r.method, r.url) for r in requests_mocker.request_history
|
DiscordRequest(r.method, r.url) for r in requests_mocker.request_history
|
||||||
]
|
]
|
||||||
|
|
||||||
self.assertListEqual(requests_made, list())
|
self.assertListEqual(requests_made, list())
|
||||||
|
|
||||||
def test_when_member_is_demoted_to_guest_then_his_account_is_deleted(
|
def test_when_member_is_demoted_to_guest_then_his_account_is_deleted(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# our user is a member and has an account
|
# our user is a member and has an account
|
||||||
self.assertTrue(self.user.has_perm('discord.access_discord'))
|
self.assertTrue(self.user.has_perm('discord.access_discord'))
|
||||||
|
|
||||||
# now we demote him to guest
|
# now we demote him to guest
|
||||||
self.member_state.member_characters.remove(self.main)
|
self.member_state.member_characters.remove(self.main)
|
||||||
|
|
||||||
# verify user is now guest
|
# verify user is now guest
|
||||||
self.user = User.objects.get(pk=self.user.pk)
|
self.user = User.objects.get(pk=self.user.pk)
|
||||||
self.assertEqual(self.user.profile.state, AuthUtils.get_guest_state())
|
self.assertEqual(self.user.profile.state, AuthUtils.get_guest_state())
|
||||||
|
|
||||||
# verify user has no longer access to Discord and no account
|
# verify user has no longer access to Discord and no account
|
||||||
self.assertFalse(self.user.has_perm('discord.access_discord'))
|
self.assertFalse(self.user.has_perm('discord.access_discord'))
|
||||||
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
# verify account was actually deleted from Discord server
|
# verify account was actually deleted from Discord server
|
||||||
requests_made = [
|
requests_made = [
|
||||||
DiscordRequest(r.method, r.url) for r in requests_mocker.request_history
|
DiscordRequest(r.method, r.url) for r in requests_mocker.request_history
|
||||||
]
|
]
|
||||||
self.assertIn(remove_guild_member_request, requests_made)
|
self.assertIn(remove_guild_member_request, requests_made)
|
||||||
|
|
||||||
# verify user has been notified
|
# verify user has been notified
|
||||||
self.assertTrue(Notification.objects.filter(user=self.user).exists())
|
self.assertTrue(Notification.objects.filter(user=self.user).exists())
|
||||||
|
|
||||||
def test_when_member_changes_to_blue_state_then_roles_are_updated_accordingly(
|
def test_when_member_changes_to_blue_state_then_roles_are_updated_accordingly(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
# request mocks
|
# request mocks
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_member_request.url,
|
guild_member_request.url,
|
||||||
json={'user': create_user_info(), 'roles': ['3', '13', '99']}
|
json={'user': create_user_info(), 'roles': ['3', '13', '99']}
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[
|
json=[
|
||||||
ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER, ROLE_BLUE
|
ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER, ROLE_BLUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
AuthUtils.disconnect_signals()
|
AuthUtils.disconnect_signals()
|
||||||
self.user.groups.add(self.group_charlie)
|
self.user.groups.add(self.group_charlie)
|
||||||
AuthUtils.connect_signals()
|
AuthUtils.connect_signals()
|
||||||
@ -264,101 +264,101 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
self.blue_state.member_characters.add(self.main)
|
self.blue_state.member_characters.add(self.main)
|
||||||
self.member_state.member_characters.remove(self.main)
|
self.member_state.member_characters.remove(self.main)
|
||||||
|
|
||||||
# verify roles for user where updated
|
# verify roles for user where updated
|
||||||
roles_updated = False
|
roles_updated = False
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
my_request = DiscordRequest(r.method, r.url)
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
if my_request == modify_guild_member_request and "roles" in r.json():
|
if my_request == modify_guild_member_request and "roles" in r.json():
|
||||||
roles_updated = True
|
roles_updated = True
|
||||||
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 98})
|
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 98})
|
||||||
break
|
break
|
||||||
|
|
||||||
self.assertTrue(roles_updated)
|
self.assertTrue(roles_updated)
|
||||||
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
def test_when_group_added_to_member_and_role_known_then_his_roles_are_updated(
|
def test_when_group_added_to_member_and_role_known_then_his_roles_are_updated(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_member_request.url,
|
guild_member_request.url,
|
||||||
json={
|
json={
|
||||||
'user': create_user_info(),
|
'user': create_user_info(),
|
||||||
'roles': ['13', '99']
|
'roles': ['13', '99']
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# adding new group to trigger signals
|
# adding new group to trigger signals
|
||||||
self.user.groups.add(self.group_charlie)
|
self.user.groups.add(self.group_charlie)
|
||||||
|
|
||||||
# verify roles for user where updated
|
# verify roles for user where updated
|
||||||
roles_updated = False
|
roles_updated = False
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
my_request = DiscordRequest(r.method, r.url)
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
if my_request == modify_guild_member_request and "roles" in r.json():
|
if my_request == modify_guild_member_request and "roles" in r.json():
|
||||||
roles_updated = True
|
roles_updated = True
|
||||||
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 99})
|
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 99})
|
||||||
break
|
break
|
||||||
|
|
||||||
self.assertTrue(roles_updated)
|
self.assertTrue(roles_updated)
|
||||||
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
def test_when_group_added_to_member_and_role_unknown_then_his_roles_are_updated(
|
def test_when_group_added_to_member_and_role_unknown_then_his_roles_are_updated(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_member_request.url,
|
guild_member_request.url,
|
||||||
json={
|
json={
|
||||||
'user': {'id': str(TEST_USER_ID), 'username': TEST_MAIN_NAME},
|
'user': {'id': str(TEST_USER_ID), 'username': TEST_MAIN_NAME},
|
||||||
'roles': ['13', '99']
|
'roles': ['13', '99']
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# adding new group to trigger signals
|
# adding new group to trigger signals
|
||||||
self.user.groups.add(self.group_charlie)
|
self.user.groups.add(self.group_charlie)
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
|
|
||||||
# verify roles for user where updated
|
# verify roles for user where updated
|
||||||
roles_updated = False
|
roles_updated = False
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
my_request = DiscordRequest(r.method, r.url)
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
if my_request == modify_guild_member_request and "roles" in r.json():
|
if my_request == modify_guild_member_request and "roles" in r.json():
|
||||||
roles_updated = True
|
roles_updated = True
|
||||||
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 99})
|
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 99})
|
||||||
break
|
break
|
||||||
|
|
||||||
self.assertTrue(roles_updated)
|
self.assertTrue(roles_updated)
|
||||||
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CELERY_ALWAYS_EAGER=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
@patch(MODULE_PATH + '.managers.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
@patch(MODULE_PATH + '.managers.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
@requests_mock.Mocker()
|
@requests_mock.Mocker()
|
||||||
class StateTestCase(TestCase):
|
class StateTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
clear_cache()
|
clear_cache()
|
||||||
reset_testdata()
|
reset_testdata()
|
||||||
|
|
||||||
self.user = AuthUtils.create_user('test_user', disconnect_signals=True)
|
self.user = AuthUtils.create_user('test_user', disconnect_signals=True)
|
||||||
AuthUtils.add_main_character(
|
AuthUtils.add_main_character(
|
||||||
self.user,
|
self.user,
|
||||||
'Perm Test Character', '99',
|
'Perm Test Character', '99',
|
||||||
corp_id='100',
|
corp_id='100',
|
||||||
alliance_id='200',
|
alliance_id='200',
|
||||||
corp_name='Perm Test Corp',
|
corp_name='Perm Test Corp',
|
||||||
alliance_name='Perm Test Alliance'
|
alliance_name='Perm Test Alliance'
|
||||||
)
|
)
|
||||||
self.test_character = EveCharacter.objects.get(character_id='99')
|
self.test_character = EveCharacter.objects.get(character_id='99')
|
||||||
@ -369,7 +369,7 @@ class StateTestCase(TestCase):
|
|||||||
self.access_discord = AuthUtils.get_permission_by_name('discord.access_discord')
|
self.access_discord = AuthUtils.get_permission_by_name('discord.access_discord')
|
||||||
self.member_state.permissions.add(self.access_discord)
|
self.member_state.permissions.add(self.access_discord)
|
||||||
self.member_state.member_characters.add(self.test_character)
|
self.member_state.member_characters.add(self.test_character)
|
||||||
|
|
||||||
def _add_discord_user(self):
|
def _add_discord_user(self):
|
||||||
self.discord_user = DiscordUser.objects.create(
|
self.discord_user = DiscordUser.objects.create(
|
||||||
user=self.user, uid="12345678910"
|
user=self.user, uid="12345678910"
|
||||||
@ -434,57 +434,57 @@ class StateTestCase(TestCase):
|
|||||||
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
@requests_mock.Mocker()
|
@requests_mock.Mocker()
|
||||||
class TestUserFeatures(WebTest):
|
class TestUserFeatures(WebTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
clear_cache()
|
clear_cache()
|
||||||
reset_testdata()
|
reset_testdata()
|
||||||
self.member = AuthUtils.create_member(TEST_USER_NAME)
|
self.member = AuthUtils.create_member(TEST_USER_NAME)
|
||||||
AuthUtils.add_main_character_2(
|
AuthUtils.add_main_character_2(
|
||||||
self.member,
|
self.member,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
disconnect_signals=True
|
disconnect_signals=True
|
||||||
)
|
)
|
||||||
add_permissions_to_members()
|
add_permissions_to_members()
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
@patch(MODULE_PATH + '.managers.OAuth2Session')
|
@patch(MODULE_PATH + '.managers.OAuth2Session')
|
||||||
def test_user_activation_normal(
|
def test_user_activation_normal(
|
||||||
self, requests_mocker, mock_OAuth2Session, mock_messages
|
self, requests_mocker, mock_OAuth2Session, mock_messages
|
||||||
):
|
):
|
||||||
# setup
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
user_get_current_request.url,
|
user_get_current_request.url,
|
||||||
json=create_user_info(
|
json=create_user_info(
|
||||||
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
requests_mocker.put(add_guild_member_request.url, status_code=201)
|
requests_mocker.put(add_guild_member_request.url, status_code=201)
|
||||||
|
|
||||||
authentication_code = 'auth_code'
|
authentication_code = 'auth_code'
|
||||||
oauth_url = 'https://www.example.com/oauth'
|
oauth_url = 'https://www.example.com/oauth'
|
||||||
state = ''
|
state = ''
|
||||||
mock_OAuth2Session.return_value.authorization_url.return_value = \
|
mock_OAuth2Session.return_value.authorization_url.return_value = \
|
||||||
oauth_url, state
|
oauth_url, state
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# user opens services page
|
# user opens services page
|
||||||
services_page = self.app.get(reverse('services:services'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
self.assertEqual(services_page.status_code, 200)
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
# user clicks Discord service activation link on page
|
# user clicks Discord service activation link on page
|
||||||
response = services_page.click(href=reverse('discord:activate'))
|
response = services_page.click(href=reverse('discord:activate'))
|
||||||
|
|
||||||
# check we got a redirect to Discord OAuth
|
# check we got a redirect to Discord OAuth
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response, expected_url=oauth_url, fetch_redirect_response=False
|
response, expected_url=oauth_url, fetch_redirect_response=False
|
||||||
)
|
)
|
||||||
@ -493,66 +493,66 @@ class TestUserFeatures(WebTest):
|
|||||||
response = self.app.get(
|
response = self.app.get(
|
||||||
reverse('discord:callback'), params={'code': authentication_code}
|
reverse('discord:callback'), params={'code': authentication_code}
|
||||||
)
|
)
|
||||||
|
|
||||||
# user got a success message
|
# user got a success message
|
||||||
self.assertTrue(mock_messages.success.called)
|
self.assertTrue(mock_messages.success.called)
|
||||||
self.assertFalse(mock_messages.error.called)
|
self.assertFalse(mock_messages.error.called)
|
||||||
|
|
||||||
requests_made = list()
|
requests_made = list()
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
obj = DiscordRequest(r.method, r.url)
|
obj = DiscordRequest(r.method, r.url)
|
||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
guild_infos_request,
|
guild_infos_request,
|
||||||
user_get_current_request,
|
user_get_current_request,
|
||||||
guild_roles_request,
|
guild_roles_request,
|
||||||
add_guild_member_request
|
add_guild_member_request
|
||||||
]
|
]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
@patch(MODULE_PATH + '.managers.OAuth2Session')
|
@patch(MODULE_PATH + '.managers.OAuth2Session')
|
||||||
def test_user_activation_failed(
|
def test_user_activation_failed(
|
||||||
self, requests_mocker, mock_OAuth2Session, mock_messages
|
self, requests_mocker, mock_OAuth2Session, mock_messages
|
||||||
):
|
):
|
||||||
# setup
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
user_get_current_request.url,
|
user_get_current_request.url,
|
||||||
json=create_user_info(
|
json=create_user_info(
|
||||||
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_exception = HTTPError('error')
|
mock_exception = HTTPError('error')
|
||||||
mock_exception.response = Mock()
|
mock_exception.response = Mock()
|
||||||
mock_exception.response.status_code = 503
|
mock_exception.response.status_code = 503
|
||||||
requests_mocker.put(add_guild_member_request.url, exc=mock_exception)
|
requests_mocker.put(add_guild_member_request.url, exc=mock_exception)
|
||||||
|
|
||||||
authentication_code = 'auth_code'
|
authentication_code = 'auth_code'
|
||||||
oauth_url = 'https://www.example.com/oauth'
|
oauth_url = 'https://www.example.com/oauth'
|
||||||
state = ''
|
state = ''
|
||||||
mock_OAuth2Session.return_value.authorization_url.return_value = \
|
mock_OAuth2Session.return_value.authorization_url.return_value = \
|
||||||
oauth_url, state
|
oauth_url, state
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# user opens services page
|
# user opens services page
|
||||||
services_page = self.app.get(reverse('services:services'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
self.assertEqual(services_page.status_code, 200)
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
# click activate on the service page
|
# click activate on the service page
|
||||||
response = services_page.click(href=reverse('discord:activate'))
|
response = services_page.click(href=reverse('discord:activate'))
|
||||||
|
|
||||||
# check we got a redirect to Discord OAuth
|
# check we got a redirect to Discord OAuth
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response, expected_url=oauth_url, fetch_redirect_response=False
|
response, expected_url=oauth_url, fetch_redirect_response=False
|
||||||
)
|
)
|
||||||
@ -561,124 +561,124 @@ class TestUserFeatures(WebTest):
|
|||||||
response = self.app.get(
|
response = self.app.get(
|
||||||
reverse('discord:callback'), params={'code': authentication_code}
|
reverse('discord:callback'), params={'code': authentication_code}
|
||||||
)
|
)
|
||||||
|
|
||||||
# user got a success message
|
# user got a success message
|
||||||
self.assertFalse(mock_messages.success.called)
|
self.assertFalse(mock_messages.success.called)
|
||||||
self.assertTrue(mock_messages.error.called)
|
self.assertTrue(mock_messages.error.called)
|
||||||
|
|
||||||
requests_made = list()
|
requests_made = list()
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
obj = DiscordRequest(r.method, r.url)
|
obj = DiscordRequest(r.method, r.url)
|
||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
guild_infos_request,
|
guild_infos_request,
|
||||||
user_get_current_request,
|
user_get_current_request,
|
||||||
guild_roles_request,
|
guild_roles_request,
|
||||||
add_guild_member_request
|
add_guild_member_request
|
||||||
]
|
]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
def test_user_deactivation_normal(self, requests_mocker, mock_messages):
|
def test_user_deactivation_normal(self, requests_mocker, mock_messages):
|
||||||
# setup
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
)
|
)
|
||||||
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
||||||
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# user opens services page
|
# user opens services page
|
||||||
services_page = self.app.get(reverse('services:services'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
self.assertEqual(services_page.status_code, 200)
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
# click deactivate on the service page
|
# click deactivate on the service page
|
||||||
response = services_page.click(href=reverse('discord:deactivate'))
|
response = services_page.click(href=reverse('discord:deactivate'))
|
||||||
|
|
||||||
# check we got a redirect to service page
|
# check we got a redirect to service page
|
||||||
self.assertRedirects(response, expected_url=reverse('services:services'))
|
self.assertRedirects(response, expected_url=reverse('services:services'))
|
||||||
|
|
||||||
# user got a success message
|
# user got a success message
|
||||||
self.assertTrue(mock_messages.success.called)
|
self.assertTrue(mock_messages.success.called)
|
||||||
self.assertFalse(mock_messages.error.called)
|
self.assertFalse(mock_messages.error.called)
|
||||||
|
|
||||||
requests_made = list()
|
requests_made = list()
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
obj = DiscordRequest(r.method, r.url)
|
obj = DiscordRequest(r.method, r.url)
|
||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [guild_infos_request, remove_guild_member_request]
|
expected = [guild_infos_request, remove_guild_member_request]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
def test_user_deactivation_fails(self, requests_mocker, mock_messages):
|
def test_user_deactivation_fails(self, requests_mocker, mock_messages):
|
||||||
# setup
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
)
|
)
|
||||||
mock_exception = HTTPError('error')
|
mock_exception = HTTPError('error')
|
||||||
mock_exception.response = Mock()
|
mock_exception.response = Mock()
|
||||||
mock_exception.response.status_code = 503
|
mock_exception.response.status_code = 503
|
||||||
requests_mocker.delete(remove_guild_member_request.url, exc=mock_exception)
|
requests_mocker.delete(remove_guild_member_request.url, exc=mock_exception)
|
||||||
|
|
||||||
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# user opens services page
|
# user opens services page
|
||||||
services_page = self.app.get(reverse('services:services'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
self.assertEqual(services_page.status_code, 200)
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
# click deactivate on the service page
|
# click deactivate on the service page
|
||||||
response = services_page.click(href=reverse('discord:deactivate'))
|
response = services_page.click(href=reverse('discord:deactivate'))
|
||||||
|
|
||||||
# check we got a redirect to service page
|
# check we got a redirect to service page
|
||||||
self.assertRedirects(response, expected_url=reverse('services:services'))
|
self.assertRedirects(response, expected_url=reverse('services:services'))
|
||||||
|
|
||||||
# user got a success message
|
# user got a success message
|
||||||
self.assertFalse(mock_messages.success.called)
|
self.assertFalse(mock_messages.success.called)
|
||||||
self.assertTrue(mock_messages.error.called)
|
self.assertTrue(mock_messages.error.called)
|
||||||
|
|
||||||
requests_made = list()
|
requests_made = list()
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
obj = DiscordRequest(r.method, r.url)
|
obj = DiscordRequest(r.method, r.url)
|
||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [guild_infos_request, remove_guild_member_request]
|
expected = [guild_infos_request, remove_guild_member_request]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
def test_user_add_new_server(self, requests_mocker, mock_messages):
|
def test_user_add_new_server(self, requests_mocker, mock_messages):
|
||||||
# setup
|
# setup
|
||||||
mock_exception = HTTPError(Mock(**{"response.status_code": 400}))
|
mock_exception = HTTPError(Mock(**{"response.status_code": 400}))
|
||||||
requests_mocker.get(guild_infos_request.url, exc=mock_exception)
|
requests_mocker.get(guild_infos_request.url, exc=mock_exception)
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.member.is_superuser = True
|
self.member.is_superuser = True
|
||||||
self.member.is_staff = True
|
self.member.is_staff = True
|
||||||
self.member.save()
|
self.member.save()
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# click deactivate on the service page
|
# click deactivate on the service page
|
||||||
response = self.app.get(reverse('services:services'))
|
response = self.app.get(reverse('services:services'))
|
||||||
|
|
||||||
# check we got can see the page and the "link server" button
|
# check we got can see the page and the "link server" button
|
||||||
self.assertEqual(response.status_int, 200)
|
self.assertEqual(response.status_int, 200)
|
||||||
self.assertIsNotNone(response.html.find(id='btnLinkDiscordServer'))
|
self.assertIsNotNone(response.html.find(id='btnLinkDiscordServer'))
|
||||||
|
|
||||||
def test_when_server_name_fails_user_can_still_see_service_page(
|
def test_when_server_name_fails_user_can_still_see_service_page(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
# setup
|
# setup
|
||||||
requests_mocker.get(guild_infos_request.url, exc=DiscordApiBackoff(1000))
|
requests_mocker.get(guild_infos_request.url, exc=DiscordApiBackoff(1000))
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# user opens services page
|
# user opens services page
|
||||||
services_page = self.app.get(reverse('services:services'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
self.assertEqual(services_page.status_code, 200)
|
self.assertEqual(services_page.status_code, 200)
|
||||||
@ -686,7 +686,7 @@ class TestUserFeatures(WebTest):
|
|||||||
@override_settings(CELERY_ALWAYS_EAGER=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
def test_server_name_is_updated_by_task(
|
def test_server_name_is_updated_by_task(
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
# setup
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
@ -696,11 +696,11 @@ class TestUserFeatures(WebTest):
|
|||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# disable API call to make sure server name is not retrieved from API
|
# disable API call to make sure server name is not retrieved from API
|
||||||
mock_exception = HTTPError(Mock(**{"response.status_code": 400}))
|
mock_exception = HTTPError(Mock(**{"response.status_code": 400}))
|
||||||
requests_mocker.get(guild_infos_request.url, exc=mock_exception)
|
requests_mocker.get(guild_infos_request.url, exc=mock_exception)
|
||||||
|
|
||||||
# user opens services page
|
# user opens services page
|
||||||
services_page = self.app.get(reverse('services:services'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
self.assertEqual(services_page.status_code, 200)
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|||||||
@ -9,21 +9,21 @@ from django.test import TestCase
|
|||||||
from allianceauth.tests.auth_utils import AuthUtils
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
TEST_GUILD_ID,
|
TEST_GUILD_ID,
|
||||||
TEST_USER_NAME,
|
TEST_USER_NAME,
|
||||||
TEST_USER_ID,
|
TEST_USER_ID,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
ROLE_ALPHA,
|
ROLE_ALPHA,
|
||||||
ROLE_BRAVO,
|
ROLE_BRAVO,
|
||||||
ROLE_CHARLIE,
|
ROLE_CHARLIE,
|
||||||
)
|
)
|
||||||
from ..discord_client.tests import create_matched_role
|
from ..discord_client.tests import create_matched_role
|
||||||
from ..app_settings import (
|
from ..app_settings import (
|
||||||
DISCORD_APP_ID,
|
DISCORD_APP_ID,
|
||||||
DISCORD_APP_SECRET,
|
DISCORD_APP_SECRET,
|
||||||
DISCORD_CALLBACK_URL,
|
DISCORD_CALLBACK_URL,
|
||||||
)
|
)
|
||||||
from ..discord_client import DiscordClient, DiscordApiBackoff
|
from ..discord_client import DiscordClient, DiscordApiBackoff
|
||||||
from ..models import DiscordUser
|
from ..models import DiscordUser
|
||||||
@ -39,32 +39,32 @@ logger = set_logger_to_file(MODULE_PATH + '.managers', __file__)
|
|||||||
@patch(MODULE_PATH + '.models.DiscordUser.objects.user_group_names')
|
@patch(MODULE_PATH + '.models.DiscordUser.objects.user_group_names')
|
||||||
@patch(MODULE_PATH + '.models.DiscordUser.objects.user_formatted_nick')
|
@patch(MODULE_PATH + '.models.DiscordUser.objects.user_formatted_nick')
|
||||||
class TestAddUser(TestCase):
|
class TestAddUser(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
self.user_info = {
|
self.user_info = {
|
||||||
'id': TEST_USER_ID,
|
'id': TEST_USER_ID,
|
||||||
'name': TEST_USER_NAME,
|
'name': TEST_USER_NAME,
|
||||||
'username': TEST_USER_NAME,
|
'username': TEST_USER_NAME,
|
||||||
'discriminator': '1234',
|
'discriminator': '1234',
|
||||||
}
|
}
|
||||||
self.access_token = 'accesstoken'
|
self.access_token = 'accesstoken'
|
||||||
|
|
||||||
def test_can_create_user_no_roles_no_nick(
|
def test_can_create_user_no_roles_no_nick(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = None
|
mock_user_formatted_nick.return_value = None
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = []
|
.return_value = []
|
||||||
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@ -79,25 +79,25 @@ class TestAddUser(TestCase):
|
|||||||
self.assertIsNone(kwargs['nick'])
|
self.assertIsNone(kwargs['nick'])
|
||||||
|
|
||||||
def test_can_create_user_with_roles_no_nick(
|
def test_can_create_user_with_roles_no_nick(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles = [
|
roles = [
|
||||||
create_matched_role(ROLE_ALPHA),
|
create_matched_role(ROLE_ALPHA),
|
||||||
create_matched_role(ROLE_BRAVO),
|
create_matched_role(ROLE_BRAVO),
|
||||||
create_matched_role(ROLE_CHARLIE)
|
create_matched_role(ROLE_CHARLIE)
|
||||||
]
|
]
|
||||||
mock_user_formatted_nick.return_value = None
|
mock_user_formatted_nick.return_value = None
|
||||||
mock_user_group_names.return_value = ['a', 'b', 'c']
|
mock_user_group_names.return_value = ['a', 'b', 'c']
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = roles
|
.return_value = roles
|
||||||
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@ -113,20 +113,20 @@ class TestAddUser(TestCase):
|
|||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', True)
|
@patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', True)
|
||||||
def test_can_create_user_no_roles_with_nick(
|
def test_can_create_user_no_roles_with_nick(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = TEST_MAIN_NAME
|
mock_user_formatted_nick.return_value = TEST_MAIN_NAME
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = []
|
.return_value = []
|
||||||
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@ -142,20 +142,20 @@ class TestAddUser(TestCase):
|
|||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', False)
|
@patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', False)
|
||||||
def test_can_create_user_no_roles_and_without_nick_if_turned_off(
|
def test_can_create_user_no_roles_and_without_nick_if_turned_off(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = TEST_MAIN_NAME
|
mock_user_formatted_nick.return_value = TEST_MAIN_NAME
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = []
|
.return_value = []
|
||||||
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
mock_DiscordClient.return_value.add_guild_member.return_value = True
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@ -168,44 +168,44 @@ class TestAddUser(TestCase):
|
|||||||
self.assertEqual(kwargs['access_token'], self.access_token)
|
self.assertEqual(kwargs['access_token'], self.access_token)
|
||||||
self.assertIsNone(kwargs['role_ids'])
|
self.assertIsNone(kwargs['role_ids'])
|
||||||
self.assertIsNone(kwargs['nick'])
|
self.assertIsNone(kwargs['nick'])
|
||||||
|
|
||||||
def test_can_activate_existing_guild_member(
|
def test_can_activate_existing_guild_member(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = None
|
mock_user_formatted_nick.return_value = None
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = []
|
.return_value = []
|
||||||
mock_DiscordClient.return_value.add_guild_member.return_value = None
|
mock_DiscordClient.return_value.add_guild_member.return_value = None
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists()
|
DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists()
|
||||||
)
|
)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
||||||
|
|
||||||
def test_return_false_when_user_creation_fails(
|
def test_return_false_when_user_creation_fails(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = None
|
mock_user_formatted_nick.return_value = None
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = []
|
.return_value = []
|
||||||
mock_DiscordClient.return_value.add_guild_member.return_value = False
|
mock_DiscordClient.return_value.add_guild_member.return_value = False
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
@ -214,21 +214,21 @@ class TestAddUser(TestCase):
|
|||||||
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
||||||
|
|
||||||
def test_return_false_when_on_api_backoff(
|
def test_return_false_when_on_api_backoff(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = None
|
mock_user_formatted_nick.return_value = None
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = []
|
.return_value = []
|
||||||
mock_DiscordClient.return_value.add_guild_member.side_effect = \
|
mock_DiscordClient.return_value.add_guild_member.side_effect = \
|
||||||
DiscordApiBackoff(999)
|
DiscordApiBackoff(999)
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
@ -237,14 +237,14 @@ class TestAddUser(TestCase):
|
|||||||
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
||||||
|
|
||||||
def test_return_false_on_http_error(
|
def test_return_false_on_http_error(
|
||||||
self,
|
self,
|
||||||
mock_user_formatted_nick,
|
mock_user_formatted_nick,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_exchange_auth_code_for_token,
|
mock_exchange_auth_code_for_token,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_formatted_nick.return_value = None
|
mock_user_formatted_nick.return_value = None
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_exchange_auth_code_for_token.return_value = self.access_token
|
mock_exchange_auth_code_for_token.return_value = self.access_token
|
||||||
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
mock_DiscordClient.return_value.current_user.return_value = self.user_info
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
@ -253,18 +253,18 @@ class TestAddUser(TestCase):
|
|||||||
mock_exception.response = Mock()
|
mock_exception.response = Mock()
|
||||||
mock_exception.response.status_code = 500
|
mock_exception.response.status_code = 500
|
||||||
mock_DiscordClient.return_value.add_guild_member.side_effect = mock_exception
|
mock_DiscordClient.return_value.add_guild_member.side_effect = mock_exception
|
||||||
|
|
||||||
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists()
|
DiscordUser.objects.filter(user=self.user, uid=TEST_USER_ID).exists()
|
||||||
)
|
)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.add_guild_member.called)
|
||||||
|
|
||||||
|
|
||||||
class TestOauthHelpers(TestCase):
|
class TestOauthHelpers(TestCase):
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DISCORD_APP_ID', '123456')
|
@patch(MODULE_PATH + '.managers.DISCORD_APP_ID', '123456')
|
||||||
def test_generate_bot_add_url(self):
|
def test_generate_bot_add_url(self):
|
||||||
bot_add_url = DiscordUser.objects.generate_bot_add_url()
|
bot_add_url = DiscordUser.objects.generate_bot_add_url()
|
||||||
|
|
||||||
@ -303,18 +303,18 @@ class TestOauthHelpers(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestUserFormattedNick(TestCase):
|
class TestUserFormattedNick(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
|
|
||||||
def test_return_nick_when_user_has_main(self):
|
def test_return_nick_when_user_has_main(self):
|
||||||
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
||||||
result = DiscordUser.objects.user_formatted_nick(self.user)
|
result = DiscordUser.objects.user_formatted_nick(self.user)
|
||||||
expected = TEST_MAIN_NAME
|
expected = TEST_MAIN_NAME
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_return_none_if_user_has_no_main(self):
|
def test_return_none_if_user_has_no_main(self):
|
||||||
result = DiscordUser.objects.user_formatted_nick(self.user)
|
result = DiscordUser.objects.user_formatted_nick(self.user)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
|
||||||
@ -325,16 +325,16 @@ class TestUserGroupNames(TestCase):
|
|||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.group_1 = Group.objects.create(name='Group 1')
|
cls.group_1 = Group.objects.create(name='Group 1')
|
||||||
cls.group_2 = Group.objects.create(name='Group 2')
|
cls.group_2 = Group.objects.create(name='Group 2')
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = AuthUtils.create_member(TEST_USER_NAME)
|
self.user = AuthUtils.create_member(TEST_USER_NAME)
|
||||||
|
|
||||||
def test_return_groups_and_state_names_for_user(self):
|
def test_return_groups_and_state_names_for_user(self):
|
||||||
self.user.groups.add(self.group_1)
|
self.user.groups.add(self.group_1)
|
||||||
result = DiscordUser.objects.user_group_names(self.user)
|
result = DiscordUser.objects.user_group_names(self.user)
|
||||||
expected = ['Group 1', 'Member']
|
expected = ['Group 1', 'Member']
|
||||||
self.assertSetEqual(set(result), set(expected))
|
self.assertSetEqual(set(result), set(expected))
|
||||||
|
|
||||||
def test_return_state_only_if_user_has_no_groups(self):
|
def test_return_state_only_if_user_has_no_groups(self):
|
||||||
result = DiscordUser.objects.user_group_names(self.user)
|
result = DiscordUser.objects.user_group_names(self.user)
|
||||||
expected = ['Member']
|
expected = ['Member']
|
||||||
@ -355,11 +355,11 @@ class TestUserHasAccount(TestCase):
|
|||||||
def test_return_false_if_user_has_no_account(self):
|
def test_return_false_if_user_has_no_account(self):
|
||||||
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
def test_return_false_if_user_does_not_exist(self):
|
def test_return_false_if_user_does_not_exist(self):
|
||||||
my_user = User(username='Dummy')
|
my_user = User(username='Dummy')
|
||||||
self.assertFalse(DiscordUser.objects.user_has_account(my_user))
|
self.assertFalse(DiscordUser.objects.user_has_account(my_user))
|
||||||
|
|
||||||
def test_return_false_if_not_called_with_user_object(self):
|
def test_return_false_if_not_called_with_user_object(self):
|
||||||
self.assertFalse(DiscordUser.objects.user_has_account('abc'))
|
self.assertFalse(DiscordUser.objects.user_has_account('abc'))
|
||||||
|
|
||||||
|
|
||||||
@ -371,7 +371,7 @@ class TestServerName(TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
|
|
||||||
def test_returns_name_when_api_returns_it(self, mock_logger, mock_DiscordClient):
|
def test_returns_name_when_api_returns_it(self, mock_logger, mock_DiscordClient):
|
||||||
server_name = "El Dorado"
|
server_name = "El Dorado"
|
||||||
mock_DiscordClient.return_value.guild_name.return_value = server_name
|
mock_DiscordClient.return_value.guild_name.return_value = server_name
|
||||||
@ -383,7 +383,7 @@ class TestServerName(TestCase):
|
|||||||
self, mock_logger, mock_DiscordClient
|
self, mock_logger, mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_exception = HTTPError('Test exception')
|
mock_exception = HTTPError('Test exception')
|
||||||
mock_exception.response = Mock(**{"status_code": 440})
|
mock_exception.response = Mock(**{"status_code": 440})
|
||||||
mock_DiscordClient.return_value.guild_name.side_effect = mock_exception
|
mock_DiscordClient.return_value.guild_name.side_effect = mock_exception
|
||||||
|
|
||||||
self.assertEqual(DiscordUser.objects.server_name(), "")
|
self.assertEqual(DiscordUser.objects.server_name(), "")
|
||||||
@ -407,7 +407,7 @@ class TestServerName(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
class TestRoleForGroup(TestCase):
|
class TestRoleForGroup(TestCase):
|
||||||
def test_return_role_if_found(self, mock_DiscordClient):
|
def test_return_role_if_found(self, mock_DiscordClient):
|
||||||
mock_DiscordClient.return_value.match_role_from_name.return_value = ROLE_ALPHA
|
mock_DiscordClient.return_value.match_role_from_name.return_value = ROLE_ALPHA
|
||||||
|
|
||||||
|
|||||||
@ -7,15 +7,15 @@ from django.test import TestCase
|
|||||||
from allianceauth.tests.auth_utils import AuthUtils
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
TEST_USER_NAME,
|
TEST_USER_NAME,
|
||||||
TEST_USER_ID,
|
TEST_USER_ID,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
ROLE_ALPHA,
|
ROLE_ALPHA,
|
||||||
ROLE_BRAVO,
|
ROLE_BRAVO,
|
||||||
ROLE_CHARLIE,
|
ROLE_CHARLIE,
|
||||||
ROLE_MIKE
|
ROLE_MIKE
|
||||||
)
|
)
|
||||||
from ..discord_client import DiscordClient, DiscordApiBackoff
|
from ..discord_client import DiscordClient, DiscordApiBackoff
|
||||||
from ..discord_client.tests import create_matched_role
|
from ..discord_client.tests import create_matched_role
|
||||||
@ -44,39 +44,39 @@ class TestBasicsAndHelpers(TestCase):
|
|||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
class TestUpdateNick(TestCase):
|
class TestUpdateNick(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
self.discord_user = DiscordUser.objects.create(
|
self.discord_user = DiscordUser.objects.create(
|
||||||
user=self.user, uid=TEST_USER_ID
|
user=self.user, uid=TEST_USER_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_update(self, mock_DiscordClient):
|
def test_can_update(self, mock_DiscordClient):
|
||||||
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
result = self.discord_user.update_nickname()
|
result = self.discord_user.update_nickname()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
def test_dont_update_if_user_has_no_main(self, mock_DiscordClient):
|
def test_dont_update_if_user_has_no_main(self, mock_DiscordClient):
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
||||||
|
|
||||||
result = self.discord_user.update_nickname()
|
result = self.discord_user.update_nickname()
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertFalse(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertFalse(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
def test_return_none_if_user_no_longer_a_member(self, mock_DiscordClient):
|
def test_return_none_if_user_no_longer_a_member(self, mock_DiscordClient):
|
||||||
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = None
|
mock_DiscordClient.return_value.modify_guild_member.return_value = None
|
||||||
|
|
||||||
result = self.discord_user.update_nickname()
|
result = self.discord_user.update_nickname()
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
def test_return_false_if_api_returns_false(self, mock_DiscordClient):
|
def test_return_false_if_api_returns_false(self, mock_DiscordClient):
|
||||||
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
AuthUtils.add_main_character_2(self.user, TEST_MAIN_NAME, TEST_MAIN_ID)
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
||||||
|
|
||||||
result = self.discord_user.update_nickname()
|
result = self.discord_user.update_nickname()
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
@ -89,16 +89,16 @@ class TestUpdateUsername(TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.discord_user = DiscordUser.objects.create(
|
self.discord_user = DiscordUser.objects.create(
|
||||||
user=self.user,
|
user=self.user,
|
||||||
uid=TEST_USER_ID,
|
uid=TEST_USER_ID,
|
||||||
username=TEST_MAIN_NAME,
|
username=TEST_MAIN_NAME,
|
||||||
discriminator='1234'
|
discriminator='1234'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_update(self, mock_DiscordClient):
|
def test_can_update(self, mock_DiscordClient):
|
||||||
new_username = 'New name'
|
new_username = 'New name'
|
||||||
new_discriminator = '9876'
|
new_discriminator = '9876'
|
||||||
user_info = {
|
user_info = {
|
||||||
@ -109,7 +109,7 @@ class TestUpdateUsername(TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mock_DiscordClient.return_value.guild_member.return_value = user_info
|
mock_DiscordClient.return_value.guild_member.return_value = user_info
|
||||||
|
|
||||||
result = self.discord_user.update_username()
|
result = self.discord_user.update_username()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.guild_member.called)
|
||||||
@ -138,7 +138,7 @@ class TestUpdateUsername(TestCase):
|
|||||||
def test_return_false_if_api_returns_corrput_data_2(self, mock_DiscordClient):
|
def test_return_false_if_api_returns_corrput_data_2(self, mock_DiscordClient):
|
||||||
user_info = {
|
user_info = {
|
||||||
'user': {
|
'user': {
|
||||||
'id': str(TEST_USER_ID),
|
'id': str(TEST_USER_ID),
|
||||||
'discriminator': '1234',
|
'discriminator': '1234',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ class TestUpdateUsername(TestCase):
|
|||||||
def test_return_false_if_api_returns_corrput_data_3(self, mock_DiscordClient):
|
def test_return_false_if_api_returns_corrput_data_3(self, mock_DiscordClient):
|
||||||
user_info = {
|
user_info = {
|
||||||
'user': {
|
'user': {
|
||||||
'id': str(TEST_USER_ID),
|
'id': str(TEST_USER_ID),
|
||||||
'username': TEST_USER_NAME,
|
'username': TEST_USER_NAME,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,12 +169,12 @@ class TestDeleteUser(TestCase):
|
|||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.discord_user = DiscordUser.objects.create(
|
self.discord_user = DiscordUser.objects.create(
|
||||||
user=self.user, uid=TEST_USER_ID
|
user=self.user, uid=TEST_USER_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_can_delete_user(self, mock_DiscordClient, mock_notify):
|
def test_can_delete_user(self, mock_DiscordClient, mock_notify):
|
||||||
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
||||||
result = self.discord_user.delete_user()
|
result = self.discord_user.delete_user()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
@ -192,7 +192,7 @@ class TestDeleteUser(TestCase):
|
|||||||
|
|
||||||
def test_can_delete_user_when_member_is_unknown(
|
def test_can_delete_user_when_member_is_unknown(
|
||||||
self, mock_DiscordClient, mock_notify
|
self, mock_DiscordClient, mock_notify
|
||||||
):
|
):
|
||||||
mock_DiscordClient.return_value.remove_guild_member.return_value = None
|
mock_DiscordClient.return_value.remove_guild_member.return_value = None
|
||||||
result = self.discord_user.delete_user()
|
result = self.discord_user.delete_user()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
@ -219,7 +219,7 @@ class TestDeleteUser(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.remove_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.remove_guild_member.called)
|
||||||
self.assertFalse(mock_notify.called)
|
self.assertFalse(mock_notify.called)
|
||||||
|
|
||||||
def test_raise_exception_on_api_backoff(
|
def test_raise_exception_on_api_backoff(
|
||||||
self, mock_DiscordClient, mock_notify
|
self, mock_DiscordClient, mock_notify
|
||||||
):
|
):
|
||||||
@ -227,7 +227,7 @@ class TestDeleteUser(TestCase):
|
|||||||
DiscordApiBackoff(999)
|
DiscordApiBackoff(999)
|
||||||
with self.assertRaises(DiscordApiBackoff):
|
with self.assertRaises(DiscordApiBackoff):
|
||||||
self.discord_user.delete_user()
|
self.discord_user.delete_user()
|
||||||
|
|
||||||
def test_return_false_on_api_backoff_and_exception_handling_on(
|
def test_return_false_on_api_backoff_and_exception_handling_on(
|
||||||
self, mock_DiscordClient, mock_notify
|
self, mock_DiscordClient, mock_notify
|
||||||
):
|
):
|
||||||
@ -244,9 +244,9 @@ class TestDeleteUser(TestCase):
|
|||||||
mock_exception.response.status_code = 500
|
mock_exception.response.status_code = 500
|
||||||
mock_DiscordClient.return_value.remove_guild_member.side_effect = \
|
mock_DiscordClient.return_value.remove_guild_member.side_effect = \
|
||||||
mock_exception
|
mock_exception
|
||||||
|
|
||||||
with self.assertRaises(HTTPError):
|
with self.assertRaises(HTTPError):
|
||||||
self.discord_user.delete_user()
|
self.discord_user.delete_user()
|
||||||
|
|
||||||
def test_return_false_on_http_error_and_exception_handling_on(
|
def test_return_false_on_http_error_and_exception_handling_on(
|
||||||
self, mock_DiscordClient, mock_notify
|
self, mock_DiscordClient, mock_notify
|
||||||
@ -264,7 +264,7 @@ class TestDeleteUser(TestCase):
|
|||||||
@patch(MODULE_PATH + '.models.DiscordUser.objects.user_group_names')
|
@patch(MODULE_PATH + '.models.DiscordUser.objects.user_group_names')
|
||||||
class TestUpdateGroups(TestCase):
|
class TestUpdateGroups(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
self.discord_user = DiscordUser.objects.create(
|
self.discord_user = DiscordUser.objects.create(
|
||||||
user=self.user, uid=TEST_USER_ID
|
user=self.user, uid=TEST_USER_ID
|
||||||
@ -272,14 +272,14 @@ class TestUpdateGroups(TestCase):
|
|||||||
self.guild_roles = [ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE]
|
self.guild_roles = [ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE]
|
||||||
self.roles_requested = [
|
self.roles_requested = [
|
||||||
create_matched_role(ROLE_ALPHA), create_matched_role(ROLE_BRAVO)
|
create_matched_role(ROLE_ALPHA), create_matched_role(ROLE_BRAVO)
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_update_if_needed(
|
def test_update_if_needed(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles_current = [1]
|
roles_current = [1]
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
@ -287,7 +287,7 @@ class TestUpdateGroups(TestCase):
|
|||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'roles': roles_current}
|
{'roles': roles_current}
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
result = self.discord_user.update_groups()
|
result = self.discord_user.update_groups()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
@ -295,11 +295,11 @@ class TestUpdateGroups(TestCase):
|
|||||||
self.assertEqual(set(kwargs['role_ids']), {1, 2})
|
self.assertEqual(set(kwargs['role_ids']), {1, 2})
|
||||||
|
|
||||||
def test_update_if_needed_and_preserve_managed_roles(
|
def test_update_if_needed_and_preserve_managed_roles(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles_current = [1, 13]
|
roles_current = [1, 13]
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
@ -307,7 +307,7 @@ class TestUpdateGroups(TestCase):
|
|||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'roles': roles_current}
|
{'roles': roles_current}
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
result = self.discord_user.update_groups()
|
result = self.discord_user.update_groups()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
@ -315,28 +315,28 @@ class TestUpdateGroups(TestCase):
|
|||||||
self.assertEqual(set(kwargs['role_ids']), {1, 2, 13})
|
self.assertEqual(set(kwargs['role_ids']), {1, 2, 13})
|
||||||
|
|
||||||
def test_dont_update_if_not_needed(
|
def test_dont_update_if_not_needed(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles_current = [1, 2, 13]
|
roles_current = [1, 2, 13]
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
mock_DiscordClient.return_value.guild_roles.return_value = self.guild_roles
|
mock_DiscordClient.return_value.guild_roles.return_value = self.guild_roles
|
||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'roles': roles_current}
|
{'roles': roles_current}
|
||||||
|
|
||||||
result = self.discord_user.update_groups()
|
result = self.discord_user.update_groups()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertFalse(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertFalse(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
def test_update_if_user_has_no_roles_on_discord(
|
def test_update_if_user_has_no_roles_on_discord(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles_current = []
|
roles_current = []
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
@ -344,30 +344,30 @@ class TestUpdateGroups(TestCase):
|
|||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'roles': roles_current}
|
{'roles': roles_current}
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
result = self.discord_user.update_groups()
|
result = self.discord_user.update_groups()
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
args, kwargs = mock_DiscordClient.return_value.modify_guild_member.call_args
|
args, kwargs = mock_DiscordClient.return_value.modify_guild_member.call_args
|
||||||
self.assertEqual(set(kwargs['role_ids']), {1, 2})
|
self.assertEqual(set(kwargs['role_ids']), {1, 2})
|
||||||
|
|
||||||
def test_return_none_if_user_no_longer_a_member(
|
def test_return_none_if_user_no_longer_a_member(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_DiscordClient.return_value.guild_member.return_value = None
|
mock_DiscordClient.return_value.guild_member.return_value = None
|
||||||
|
|
||||||
result = self.discord_user.update_groups()
|
result = self.discord_user.update_groups()
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
self.assertFalse(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertFalse(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
def test_return_false_if_api_returns_false(
|
def test_return_false_if_api_returns_false(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles_current = [1]
|
roles_current = [1]
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
@ -375,17 +375,17 @@ class TestUpdateGroups(TestCase):
|
|||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'roles': roles_current}
|
{'roles': roles_current}
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
||||||
|
|
||||||
result = self.discord_user.update_groups()
|
result = self.discord_user.update_groups()
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
def test_raise_exception_if_member_has_unknown_roles(
|
def test_raise_exception_if_member_has_unknown_roles(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
roles_current = [99]
|
roles_current = [99]
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
@ -393,21 +393,21 @@ class TestUpdateGroups(TestCase):
|
|||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'roles': roles_current}
|
{'roles': roles_current}
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
self.discord_user.update_groups()
|
self.discord_user.update_groups()
|
||||||
|
|
||||||
def test_refresh_guild_roles_user_roles_dont_not_match(
|
def test_refresh_guild_roles_user_roles_dont_not_match(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
def my_guild_roles(guild_id, use_cache=True):
|
def my_guild_roles(guild_id, use_cache=True):
|
||||||
if use_cache:
|
if use_cache:
|
||||||
return [ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE]
|
return [ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE]
|
||||||
else:
|
else:
|
||||||
return [ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE]
|
return [ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE]
|
||||||
|
|
||||||
roles_current = [3]
|
roles_current = [3]
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
@ -421,10 +421,10 @@ class TestUpdateGroups(TestCase):
|
|||||||
self.assertEqual(mock_DiscordClient.return_value.guild_roles.call_count, 2)
|
self.assertEqual(mock_DiscordClient.return_value.guild_roles.call_count, 2)
|
||||||
|
|
||||||
def test_raise_exception_if_member_info_is_invalid(
|
def test_raise_exception_if_member_info_is_invalid(
|
||||||
self,
|
self,
|
||||||
mock_user_group_names,
|
mock_user_group_names,
|
||||||
mock_DiscordClient
|
mock_DiscordClient
|
||||||
):
|
):
|
||||||
mock_user_group_names.return_value = []
|
mock_user_group_names.return_value = []
|
||||||
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
mock_DiscordClient.return_value.match_or_create_roles_from_names\
|
||||||
.return_value = self.roles_requested
|
.return_value = self.roles_requested
|
||||||
@ -432,6 +432,6 @@ class TestUpdateGroups(TestCase):
|
|||||||
mock_DiscordClient.return_value.guild_member.return_value = \
|
mock_DiscordClient.return_value.guild_member.return_value = \
|
||||||
{'user': 'dummy'}
|
{'user': 'dummy'}
|
||||||
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
self.discord_user.update_groups()
|
self.discord_user.update_groups()
|
||||||
|
|||||||
@ -23,7 +23,7 @@ logger = set_logger_to_file(MODULE_PATH, __file__)
|
|||||||
@patch(MODULE_PATH + '.DiscordUser.update_groups')
|
@patch(MODULE_PATH + '.DiscordUser.update_groups')
|
||||||
@patch(MODULE_PATH + ".logger")
|
@patch(MODULE_PATH + ".logger")
|
||||||
class TestUpdateGroups(TestCase):
|
class TestUpdateGroups(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
@ -32,7 +32,7 @@ class TestUpdateGroups(TestCase):
|
|||||||
cls.group_2 = Group.objects.create(name='Group 2')
|
cls.group_2 = Group.objects.create(name='Group 2')
|
||||||
cls.group_1.user_set.add(cls.user)
|
cls.group_1.user_set.add(cls.user)
|
||||||
cls.group_2.user_set.add(cls.user)
|
cls.group_2.user_set.add(cls.user)
|
||||||
|
|
||||||
def test_can_update_groups(self, mock_logger, mock_update_groups):
|
def test_can_update_groups(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
@ -43,7 +43,7 @@ class TestUpdateGroups(TestCase):
|
|||||||
):
|
):
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
self.assertFalse(mock_update_groups.called)
|
self.assertFalse(mock_update_groups.called)
|
||||||
|
|
||||||
def test_retries_on_api_backoff(self, mock_logger, mock_update_groups):
|
def test_retries_on_api_backoff(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_exception = DiscordApiBackoff(999)
|
mock_exception = DiscordApiBackoff(999)
|
||||||
@ -63,7 +63,7 @@ class TestUpdateGroups(TestCase):
|
|||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
self.assertTrue(mock_logger.warning.called)
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
def test_retry_on_http_error_404_when_user_not_deleted(
|
def test_retry_on_http_error_404_when_user_not_deleted(
|
||||||
self, mock_logger, mock_update_groups
|
self, mock_logger, mock_update_groups
|
||||||
):
|
):
|
||||||
@ -77,8 +77,8 @@ class TestUpdateGroups(TestCase):
|
|||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
self.assertTrue(mock_logger.warning.called)
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
def test_retry_on_non_http_error(self, mock_logger, mock_update_groups):
|
def test_retry_on_non_http_error(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_update_groups.side_effect = ConnectionError
|
mock_update_groups.side_effect = ConnectionError
|
||||||
|
|
||||||
@ -86,23 +86,23 @@ class TestUpdateGroups(TestCase):
|
|||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
self.assertTrue(mock_logger.warning.called)
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
||||||
def test_log_error_if_retries_exhausted(self, mock_logger, mock_update_groups):
|
def test_log_error_if_retries_exhausted(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_task = MagicMock(**{'request.retries': 3})
|
mock_task = MagicMock(**{'request.retries': 3})
|
||||||
mock_update_groups.side_effect = ConnectionError
|
mock_update_groups.side_effect = ConnectionError
|
||||||
update_groups_inner = tasks.update_groups.__wrapped__.__func__
|
update_groups_inner = tasks.update_groups.__wrapped__.__func__
|
||||||
|
|
||||||
update_groups_inner(mock_task, self.user.pk)
|
update_groups_inner(mock_task, self.user.pk)
|
||||||
self.assertTrue(mock_logger.error.called)
|
self.assertTrue(mock_logger.error.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.delete_user.delay')
|
@patch(MODULE_PATH + '.delete_user.delay')
|
||||||
def test_delete_user_if_user_is_no_longer_member_of_discord_server(
|
def test_delete_user_if_user_is_no_longer_member_of_discord_server(
|
||||||
self, mock_delete_user, mock_logger, mock_update_groups
|
self, mock_delete_user, mock_logger, mock_update_groups
|
||||||
):
|
):
|
||||||
mock_update_groups.return_value = None
|
mock_update_groups.return_value = None
|
||||||
|
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
self.assertTrue(mock_update_groups.called)
|
self.assertTrue(mock_update_groups.called)
|
||||||
@ -111,45 +111,45 @@ class TestUpdateGroups(TestCase):
|
|||||||
|
|
||||||
@patch(MODULE_PATH + '.DiscordUser.update_nickname')
|
@patch(MODULE_PATH + '.DiscordUser.update_nickname')
|
||||||
class TestUpdateNickname(TestCase):
|
class TestUpdateNickname(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.user = AuthUtils.create_member(TEST_USER_NAME)
|
cls.user = AuthUtils.create_member(TEST_USER_NAME)
|
||||||
AuthUtils.add_main_character_2(
|
AuthUtils.add_main_character_2(
|
||||||
cls.user,
|
cls.user,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
corp_id='2',
|
corp_id='2',
|
||||||
corp_name='test_corp',
|
corp_name='test_corp',
|
||||||
corp_ticker='TEST',
|
corp_ticker='TEST',
|
||||||
disconnect_signals=True
|
disconnect_signals=True
|
||||||
)
|
)
|
||||||
cls.discord_user = DiscordUser.objects.create(user=cls.user, uid=TEST_USER_ID)
|
cls.discord_user = DiscordUser.objects.create(user=cls.user, uid=TEST_USER_ID)
|
||||||
|
|
||||||
def test_can_update_nickname(self, mock_update_nickname):
|
def test_can_update_nickname(self, mock_update_nickname):
|
||||||
mock_update_nickname.return_value = True
|
mock_update_nickname.return_value = True
|
||||||
|
|
||||||
tasks.update_nickname(self.user.pk)
|
tasks.update_nickname(self.user.pk)
|
||||||
self.assertTrue(mock_update_nickname.called)
|
self.assertTrue(mock_update_nickname.called)
|
||||||
|
|
||||||
def test_no_action_when_user_had_no_account(self, mock_update_nickname):
|
def test_no_action_when_user_had_no_account(self, mock_update_nickname):
|
||||||
my_user = AuthUtils.create_user('Dummy User')
|
my_user = AuthUtils.create_user('Dummy User')
|
||||||
mock_update_nickname.return_value = False
|
mock_update_nickname.return_value = False
|
||||||
|
|
||||||
tasks.update_nickname(my_user.pk)
|
tasks.update_nickname(my_user.pk)
|
||||||
self.assertFalse(mock_update_nickname.called)
|
self.assertFalse(mock_update_nickname.called)
|
||||||
|
|
||||||
def test_retries_on_api_backoff(self, mock_update_nickname):
|
def test_retries_on_api_backoff(self, mock_update_nickname):
|
||||||
mock_exception = DiscordApiBackoff(999)
|
mock_exception = DiscordApiBackoff(999)
|
||||||
mock_update_nickname.side_effect = mock_exception
|
mock_update_nickname.side_effect = mock_exception
|
||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_nickname(self.user.pk)
|
tasks.update_nickname(self.user.pk)
|
||||||
|
|
||||||
def test_retries_on_general_exception(self, mock_update_nickname):
|
def test_retries_on_general_exception(self, mock_update_nickname):
|
||||||
mock_update_nickname.side_effect = ConnectionError
|
mock_update_nickname.side_effect = ConnectionError
|
||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_nickname(self.user.pk)
|
tasks.update_nickname(self.user.pk)
|
||||||
|
|
||||||
@ -158,9 +158,9 @@ class TestUpdateNickname(TestCase):
|
|||||||
mock_task = MagicMock(**{'request.retries': 3})
|
mock_task = MagicMock(**{'request.retries': 3})
|
||||||
mock_update_nickname.side_effect = ConnectionError
|
mock_update_nickname.side_effect = ConnectionError
|
||||||
update_nickname_inner = tasks.update_nickname.__wrapped__.__func__
|
update_nickname_inner = tasks.update_nickname.__wrapped__.__func__
|
||||||
|
|
||||||
update_nickname_inner(mock_task, self.user.pk)
|
update_nickname_inner(mock_task, self.user.pk)
|
||||||
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.DiscordUser.update_username')
|
@patch(MODULE_PATH + '.DiscordUser.update_username')
|
||||||
class TestUpdateUsername(TestCase):
|
class TestUpdateUsername(TestCase):
|
||||||
@ -206,7 +206,7 @@ class TestDeleteUser(TestCase):
|
|||||||
self, mock_delete_user_delay, mock_delete_user
|
self, mock_delete_user_delay, mock_delete_user
|
||||||
):
|
):
|
||||||
mock_delete_user.return_value = None
|
mock_delete_user.return_value = None
|
||||||
|
|
||||||
tasks.delete_user(self.user.pk)
|
tasks.delete_user(self.user.pk)
|
||||||
self.assertTrue(mock_delete_user.called)
|
self.assertTrue(mock_delete_user.called)
|
||||||
self.assertFalse(mock_delete_user_delay.called)
|
self.assertFalse(mock_delete_user_delay.called)
|
||||||
@ -218,15 +218,15 @@ class TestTaskPerformUserAction(TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.user = AuthUtils.create_member('Peter Parker')
|
cls.user = AuthUtils.create_member('Peter Parker')
|
||||||
cls.discord_user = DiscordUser.objects.create(user=cls.user, uid=TEST_USER_ID)
|
cls.discord_user = DiscordUser.objects.create(user=cls.user, uid=TEST_USER_ID)
|
||||||
|
|
||||||
def test_raise_value_error_on_unknown_method(self, mock_update_groups):
|
def test_raise_value_error_on_unknown_method(self, mock_update_groups):
|
||||||
mock_task = MagicMock(**{'request.retries': 0})
|
mock_task = MagicMock(**{'request.retries': 0})
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
tasks._task_perform_user_action(mock_task, self.user.pk, 'invalid_method')
|
tasks._task_perform_user_action(mock_task, self.user.pk, 'invalid_method')
|
||||||
|
|
||||||
def test_catch_and_log_unexpected_exceptions(self, mock_update_groups):
|
def test_catch_and_log_unexpected_exceptions(self, mock_update_groups):
|
||||||
mock_task = MagicMock(**{'request.retries': 0})
|
mock_task = MagicMock(**{'request.retries': 0})
|
||||||
mock_update_groups.side_effect = RuntimeError
|
mock_update_groups.side_effect = RuntimeError
|
||||||
@ -253,8 +253,8 @@ class TestTaskUpdateServername(TestCase):
|
|||||||
|
|
||||||
self.assertFalse(mock_logger.error.called)
|
self.assertFalse(mock_logger.error.called)
|
||||||
|
|
||||||
def test_retry_on_http_error(self, mock_logger, mock_server_name):
|
def test_retry_on_http_error(self, mock_logger, mock_server_name):
|
||||||
mock_exception = HTTPError(MagicMock(**{"response.status_code": 500}))
|
mock_exception = HTTPError(MagicMock(**{"response.status_code": 500}))
|
||||||
mock_server_name.side_effect = mock_exception
|
mock_server_name.side_effect = mock_exception
|
||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
@ -262,20 +262,20 @@ class TestTaskUpdateServername(TestCase):
|
|||||||
|
|
||||||
self.assertTrue(mock_logger.warning.called)
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
def test_retry_on_connection_error(self, mock_logger, mock_server_name):
|
def test_retry_on_connection_error(self, mock_logger, mock_server_name):
|
||||||
mock_server_name.side_effect = ConnectionError
|
mock_server_name.side_effect = ConnectionError
|
||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_servername()
|
tasks.update_servername()
|
||||||
|
|
||||||
self.assertTrue(mock_logger.warning.called)
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
||||||
def test_log_error_if_retries_exhausted(self, mock_logger, mock_server_name):
|
def test_log_error_if_retries_exhausted(self, mock_logger, mock_server_name):
|
||||||
mock_task = MagicMock(**{'request.retries': 3})
|
mock_task = MagicMock(**{'request.retries': 3})
|
||||||
mock_server_name.side_effect = ConnectionError
|
mock_server_name.side_effect = ConnectionError
|
||||||
update_groups_inner = tasks.update_servername.__wrapped__.__func__
|
update_groups_inner = tasks.update_servername.__wrapped__.__func__
|
||||||
|
|
||||||
update_groups_inner(mock_task)
|
update_groups_inner(mock_task)
|
||||||
self.assertTrue(mock_logger.error.called)
|
self.assertTrue(mock_logger.error.called)
|
||||||
|
|
||||||
@ -285,24 +285,24 @@ class TestTaskPerformUsersAction(TestCase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
|
|
||||||
def test_raise_value_error_on_unknown_method(self, mock_server_name):
|
def test_raise_value_error_on_unknown_method(self, mock_server_name):
|
||||||
mock_task = MagicMock(**{'request.retries': 0})
|
mock_task = MagicMock(**{'request.retries': 0})
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
tasks._task_perform_users_action(mock_task, 'invalid_method')
|
tasks._task_perform_users_action(mock_task, 'invalid_method')
|
||||||
|
|
||||||
def test_catch_and_log_unexpected_exceptions(self, mock_server_name):
|
def test_catch_and_log_unexpected_exceptions(self, mock_server_name):
|
||||||
mock_server_name.side_effect = RuntimeError
|
mock_server_name.side_effect = RuntimeError
|
||||||
mock_task = MagicMock(**{'request.retries': 0})
|
mock_task = MagicMock(**{'request.retries': 0})
|
||||||
|
|
||||||
tasks._task_perform_users_action(mock_task, 'server_name')
|
tasks._task_perform_users_action(mock_task, 'server_name')
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CELERY_ALWAYS_EAGER=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
class TestBulkTasks(TestCase):
|
class TestBulkTasks(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
@ -321,7 +321,7 @@ class TestBulkTasks(TestCase):
|
|||||||
tasks.update_groups_bulk(expected_pks)
|
tasks.update_groups_bulk(expected_pks)
|
||||||
self.assertEqual(mock_update_groups.call_count, 2)
|
self.assertEqual(mock_update_groups.call_count, 2)
|
||||||
current_pks = [args[0][0] for args in mock_update_groups.call_args_list]
|
current_pks = [args[0][0] for args in mock_update_groups.call_args_list]
|
||||||
|
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.update_groups.si')
|
@patch(MODULE_PATH + '.update_groups.si')
|
||||||
@ -347,7 +347,7 @@ class TestBulkTasks(TestCase):
|
|||||||
self.assertEqual(mock_update_nickname.call_count, 2)
|
self.assertEqual(mock_update_nickname.call_count, 2)
|
||||||
current_pks = [
|
current_pks = [
|
||||||
args[0][0] for args in mock_update_nickname.call_args_list
|
args[0][0] for args in mock_update_nickname.call_args_list
|
||||||
]
|
]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.update_nickname.si')
|
@patch(MODULE_PATH + '.update_nickname.si')
|
||||||
@ -374,11 +374,11 @@ class TestBulkTasks(TestCase):
|
|||||||
tasks.update_usernames_bulk(expected_pks)
|
tasks.update_usernames_bulk(expected_pks)
|
||||||
self.assertEqual(mock_update_username.call_count, 2)
|
self.assertEqual(mock_update_username.call_count, 2)
|
||||||
current_pks = [args[0][0] for args in mock_update_username.call_args_list]
|
current_pks = [args[0][0] for args in mock_update_username.call_args_list]
|
||||||
|
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.update_username')
|
@patch(MODULE_PATH + '.update_username')
|
||||||
@patch(MODULE_PATH + '.update_servername')
|
@patch(MODULE_PATH + '.update_servername')
|
||||||
def test_can_update_all_usernames(
|
def test_can_update_all_usernames(
|
||||||
self, mock_update_servername, mock_update_username
|
self, mock_update_servername, mock_update_username
|
||||||
):
|
):
|
||||||
@ -405,7 +405,7 @@ class TestBulkTasks(TestCase):
|
|||||||
du_3 = DiscordUser.objects.create(user=self.user_3, uid=789)
|
du_3 = DiscordUser.objects.create(user=self.user_3, uid=789)
|
||||||
|
|
||||||
tasks.update_all()
|
tasks.update_all()
|
||||||
self.assertEqual(mock_update_groups.si.call_count, 3)
|
self.assertEqual(mock_update_groups.si.call_count, 3)
|
||||||
current_pks = [args[0][0] for args in mock_update_groups.si.call_args_list]
|
current_pks = [args[0][0] for args in mock_update_groups.si.call_args_list]
|
||||||
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
@ -415,7 +415,7 @@ class TestBulkTasks(TestCase):
|
|||||||
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
self.assertEqual(mock_update_usernames.si.call_count, 3)
|
self.assertEqual(mock_update_usernames.si.call_count, 3)
|
||||||
current_pks = [args[0][0] for args in mock_update_usernames.si.call_args_list]
|
current_pks = [args[0][0] for args in mock_update_usernames.si.call_args_list]
|
||||||
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
@ -432,14 +432,14 @@ class TestBulkTasks(TestCase):
|
|||||||
du_3 = DiscordUser.objects.create(user=self.user_3, uid=789)
|
du_3 = DiscordUser.objects.create(user=self.user_3, uid=789)
|
||||||
|
|
||||||
tasks.update_all()
|
tasks.update_all()
|
||||||
self.assertEqual(mock_update_groups.si.call_count, 3)
|
self.assertEqual(mock_update_groups.si.call_count, 3)
|
||||||
current_pks = [args[0][0] for args in mock_update_groups.si.call_args_list]
|
current_pks = [args[0][0] for args in mock_update_groups.si.call_args_list]
|
||||||
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
self.assertEqual(mock_update_nickname.si.call_count, 0)
|
self.assertEqual(mock_update_nickname.si.call_count, 0)
|
||||||
|
|
||||||
self.assertEqual(mock_update_usernames.si.call_count, 3)
|
self.assertEqual(mock_update_usernames.si.call_count, 3)
|
||||||
current_pks = [args[0][0] for args in mock_update_usernames.si.call_args_list]
|
current_pks = [args[0][0] for args in mock_update_usernames.si.call_args_list]
|
||||||
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|||||||
@ -9,19 +9,19 @@ MODULE_PATH = 'allianceauth.services.modules.discord.utils'
|
|||||||
class TestCleanSetting(TestCase):
|
class TestCleanSetting(TestCase):
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.settings')
|
@patch(MODULE_PATH + '.settings')
|
||||||
def test_default_if_not_set(self, mock_settings):
|
def test_default_if_not_set(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.settings')
|
@patch(MODULE_PATH + '.settings')
|
||||||
def test_default_if_not_set_for_none(self, mock_settings):
|
def test_default_if_not_set_for_none(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
mock_settings.TEST_SETTING_DUMMY = Mock(spec=None)
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
None,
|
None,
|
||||||
required_type=int
|
required_type=int
|
||||||
)
|
)
|
||||||
@ -31,8 +31,8 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_true_stays_true(self, mock_settings):
|
def test_true_stays_true(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = True
|
mock_settings.TEST_SETTING_DUMMY = True
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
self.assertEqual(result, True)
|
self.assertEqual(result, True)
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_false_stays_false(self, mock_settings):
|
def test_false_stays_false(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = False
|
mock_settings.TEST_SETTING_DUMMY = False
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False
|
False
|
||||||
)
|
)
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
@ -49,7 +49,7 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_default_for_invalid_type_bool(self, mock_settings):
|
def test_default_for_invalid_type_bool(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
False
|
False
|
||||||
)
|
)
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
@ -58,7 +58,7 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_default_for_invalid_type_int(self, mock_settings):
|
def test_default_for_invalid_type_int(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
50
|
50
|
||||||
)
|
)
|
||||||
self.assertEqual(result, 50)
|
self.assertEqual(result, 50)
|
||||||
@ -67,7 +67,7 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_default_if_below_minimum_1(self, mock_settings):
|
def test_default_if_below_minimum_1(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = -5
|
mock_settings.TEST_SETTING_DUMMY = -5
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=50
|
default_value=50
|
||||||
)
|
)
|
||||||
self.assertEqual(result, 50)
|
self.assertEqual(result, 50)
|
||||||
@ -76,7 +76,7 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_default_if_below_minimum_2(self, mock_settings):
|
def test_default_if_below_minimum_2(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = -50
|
mock_settings.TEST_SETTING_DUMMY = -50
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=50,
|
default_value=50,
|
||||||
min_value=-10
|
min_value=-10
|
||||||
)
|
)
|
||||||
@ -86,7 +86,7 @@ class TestCleanSetting(TestCase):
|
|||||||
def test_default_for_invalid_type_int_2(self, mock_settings):
|
def test_default_for_invalid_type_int_2(self, mock_settings):
|
||||||
mock_settings.TEST_SETTING_DUMMY = 1000
|
mock_settings.TEST_SETTING_DUMMY = 1000
|
||||||
result = clean_setting(
|
result = clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=50,
|
default_value=50,
|
||||||
max_value=100
|
max_value=100
|
||||||
)
|
)
|
||||||
@ -97,6 +97,6 @@ class TestCleanSetting(TestCase):
|
|||||||
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
mock_settings.TEST_SETTING_DUMMY = 'invalid type'
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
clean_setting(
|
clean_setting(
|
||||||
'TEST_SETTING_DUMMY',
|
'TEST_SETTING_DUMMY',
|
||||||
default_value=None
|
default_value=None
|
||||||
)
|
)
|
||||||
|
|||||||
@ -11,10 +11,10 @@ from ..discord_client import DiscordClient
|
|||||||
from ..models import DiscordUser
|
from ..models import DiscordUser
|
||||||
from ..utils import set_logger_to_file
|
from ..utils import set_logger_to_file
|
||||||
from ..views import (
|
from ..views import (
|
||||||
discord_callback,
|
discord_callback,
|
||||||
reset_discord,
|
reset_discord,
|
||||||
deactivate_discord,
|
deactivate_discord,
|
||||||
discord_add_bot,
|
discord_add_bot,
|
||||||
activate_discord
|
activate_discord
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,10 +49,10 @@ class TestActivateDiscord(SetupClassMixin, TestCase):
|
|||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
class TestDeactivateDiscord(SetupClassMixin, TestCase):
|
class TestDeactivateDiscord(SetupClassMixin, TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
|
|
||||||
def test_when_successful_show_success_message(
|
def test_when_successful_show_success_message(
|
||||||
self, mock_DiscordClient, mock_messages
|
self, mock_DiscordClient, mock_messages
|
||||||
):
|
):
|
||||||
@ -81,7 +81,7 @@ class TestDeactivateDiscord(SetupClassMixin, TestCase):
|
|||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient')
|
@patch(MODULE_PATH + '.managers.DiscordClient')
|
||||||
class TestResetDiscord(SetupClassMixin, TestCase):
|
class TestResetDiscord(SetupClassMixin, TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ class TestResetDiscord(SetupClassMixin, TestCase):
|
|||||||
request.user = self.user
|
request.user = self.user
|
||||||
response = reset_discord(request)
|
response = reset_discord(request)
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertEqual(response.url, reverse("discord:activate"))
|
self.assertEqual(response.url, reverse("discord:activate"))
|
||||||
self.assertFalse(mock_messages.error.called)
|
self.assertFalse(mock_messages.error.called)
|
||||||
|
|
||||||
def test_when_unsuccessful_message_error_and_redirect_to_service(
|
def test_when_unsuccessful_message_error_and_redirect_to_service(
|
||||||
@ -111,7 +111,7 @@ class TestResetDiscord(SetupClassMixin, TestCase):
|
|||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
@patch(MODULE_PATH + '.views.DiscordUser.objects.add_user')
|
@patch(MODULE_PATH + '.views.DiscordUser.objects.add_user')
|
||||||
class TestDiscordCallback(SetupClassMixin, TestCase):
|
class TestDiscordCallback(SetupClassMixin, TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ class TestDiscordCallback(SetupClassMixin, TestCase):
|
|||||||
self.assertEqual(response.url, self.services_url)
|
self.assertEqual(response.url, self.services_url)
|
||||||
self.assertTrue(mock_messages.success.called)
|
self.assertTrue(mock_messages.success.called)
|
||||||
self.assertFalse(mock_messages.error.called)
|
self.assertFalse(mock_messages.error.called)
|
||||||
|
|
||||||
def test_handle_no_code(self, mock_add_user, mock_messages):
|
def test_handle_no_code(self, mock_add_user, mock_messages):
|
||||||
mock_add_user.return_value = True
|
mock_add_user.return_value = True
|
||||||
request = self.factory.get(
|
request = self.factory.get(
|
||||||
@ -138,7 +138,7 @@ class TestDiscordCallback(SetupClassMixin, TestCase):
|
|||||||
self.assertEqual(response.url, self.services_url)
|
self.assertEqual(response.url, self.services_url)
|
||||||
self.assertFalse(mock_messages.success.called)
|
self.assertFalse(mock_messages.success.called)
|
||||||
self.assertTrue(mock_messages.error.called)
|
self.assertTrue(mock_messages.error.called)
|
||||||
|
|
||||||
def test_error_message_when_user_creation_failed(
|
def test_error_message_when_user_creation_failed(
|
||||||
self, mock_add_user, mock_messages
|
self, mock_add_user, mock_messages
|
||||||
):
|
):
|
||||||
@ -156,7 +156,7 @@ class TestDiscordCallback(SetupClassMixin, TestCase):
|
|||||||
|
|
||||||
@patch(MODULE_PATH + '.views.DiscordUser.objects.generate_bot_add_url')
|
@patch(MODULE_PATH + '.views.DiscordUser.objects.generate_bot_add_url')
|
||||||
class TestDiscordAddBot(TestCase):
|
class TestDiscordAddBot(TestCase):
|
||||||
|
|
||||||
def test_add_bot(self, mock_generate_bot_add_url):
|
def test_add_bot(self, mock_generate_bot_add_url):
|
||||||
bot_url = 'https://www.example.com/bot'
|
bot_url = 'https://www.example.com/bot'
|
||||||
mock_generate_bot_add_url.return_value = bot_url
|
mock_generate_bot_add_url.return_value = bot_url
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class LoggerAddTag(logging.LoggerAdapter):
|
|||||||
|
|
||||||
def process(self, msg, kwargs):
|
def process(self, msg, kwargs):
|
||||||
return '[%s] %s' % (self.prefix, msg), kwargs
|
return '[%s] %s' % (self.prefix, msg), kwargs
|
||||||
|
|
||||||
|
|
||||||
def clean_setting(
|
def clean_setting(
|
||||||
name: str,
|
name: str,
|
||||||
@ -58,7 +58,7 @@ def clean_setting(
|
|||||||
'You setting for %s it not valid. Please correct it. '
|
'You setting for %s it not valid. Please correct it. '
|
||||||
'Using default for now: %s',
|
'Using default for now: %s',
|
||||||
name,
|
name,
|
||||||
default_value
|
default_value
|
||||||
)
|
)
|
||||||
cleaned_value = default_value
|
cleaned_value = default_value
|
||||||
return cleaned_value
|
return cleaned_value
|
||||||
@ -66,15 +66,15 @@ def clean_setting(
|
|||||||
|
|
||||||
def set_logger_to_file(logger_name: str, name: str) -> object:
|
def set_logger_to_file(logger_name: str, name: str) -> object:
|
||||||
"""set logger for current module to log into a file. Useful for tests.
|
"""set logger for current module to log into a file. Useful for tests.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
- logger: current logger object
|
- logger: current logger object
|
||||||
- name: name of current module, e.g. __file__
|
- name: name of current module, e.g. __file__
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- amended logger
|
- amended logger
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# reconfigure logger so we get logging from tested module
|
# reconfigure logger so we get logging from tested module
|
||||||
f_format = logging.Formatter(
|
f_format = logging.Formatter(
|
||||||
'%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s'
|
'%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s'
|
||||||
|
|||||||
@ -47,11 +47,11 @@ def reset_discord(request):
|
|||||||
):
|
):
|
||||||
logger.info(
|
logger.info(
|
||||||
"Successfully deleted discord user for user %s - "
|
"Successfully deleted discord user for user %s - "
|
||||||
"forwarding to discord activation.",
|
"forwarding to discord activation.",
|
||||||
request.user
|
request.user
|
||||||
)
|
)
|
||||||
return redirect("discord:activate")
|
return redirect("discord:activate")
|
||||||
|
|
||||||
logger.error(
|
logger.error(
|
||||||
"Unsuccessful attempt to reset discord for user %s", request.user
|
"Unsuccessful attempt to reset discord for user %s", request.user
|
||||||
)
|
)
|
||||||
@ -74,7 +74,7 @@ def discord_callback(request):
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
"Received Discord callback for activation of user %s", request.user
|
"Received Discord callback for activation of user %s", request.user
|
||||||
)
|
)
|
||||||
authorization_code = request.GET.get('code', None)
|
authorization_code = request.GET.get('code', None)
|
||||||
if not authorization_code:
|
if not authorization_code:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Did not receive OAuth code from callback for user %s", request.user
|
"Did not receive OAuth code from callback for user %s", request.user
|
||||||
@ -82,34 +82,34 @@ def discord_callback(request):
|
|||||||
success = False
|
success = False
|
||||||
else:
|
else:
|
||||||
if DiscordUser.objects.add_user(
|
if DiscordUser.objects.add_user(
|
||||||
user=request.user,
|
user=request.user,
|
||||||
authorization_code=authorization_code,
|
authorization_code=authorization_code,
|
||||||
is_rate_limited=False
|
is_rate_limited=False
|
||||||
):
|
):
|
||||||
logger.info(
|
logger.info(
|
||||||
"Successfully activated Discord account for user %s", request.user
|
"Successfully activated Discord account for user %s", request.user
|
||||||
)
|
)
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Failed to activate Discord account for user %s", request.user
|
"Failed to activate Discord account for user %s", request.user
|
||||||
)
|
)
|
||||||
success = False
|
success = False
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
messages.success(
|
messages.success(
|
||||||
request, _('Your Discord account has been successfully activated.')
|
request, _('Your Discord account has been successfully activated.')
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
_(
|
_(
|
||||||
'An error occurred while trying to activate your Discord account. '
|
'An error occurred while trying to activate your Discord account. '
|
||||||
'Please try again.'
|
'Please try again.'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return redirect("services:services")
|
return redirect("services:services")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,6 @@ from ...admin import ServicesUserAdmin
|
|||||||
|
|
||||||
@admin.register(DiscourseUser)
|
@admin.register(DiscourseUser)
|
||||||
class DiscourseUserAdmin(ServicesUserAdmin):
|
class DiscourseUserAdmin(ServicesUserAdmin):
|
||||||
list_display = ServicesUserAdmin.list_display + (
|
list_display = ServicesUserAdmin.list_display + (
|
||||||
'enabled',
|
'enabled',
|
||||||
)
|
)
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class ExampleService(ServicesHook):
|
|||||||
urls = self.Urls()
|
urls = self.Urls()
|
||||||
# urls.auth_activate = 'auth_example_activate'
|
# urls.auth_activate = 'auth_example_activate'
|
||||||
# urls.auth_deactivate = 'auth_example_deactivate'
|
# urls.auth_deactivate = 'auth_example_deactivate'
|
||||||
# urls.auth_reset_password = 'auth_example_reset_password'
|
# urls.auth_reset_password = 'auth_example_reset_password'
|
||||||
# urls.auth_set_password = 'auth_example_set_password'
|
# urls.auth_set_password = 'auth_example_set_password'
|
||||||
return render_to_string(self.service_ctrl_template, {
|
return render_to_string(self.service_ctrl_template, {
|
||||||
'service_name': self.title,
|
'service_name': self.title,
|
||||||
|
|||||||
@ -17,7 +17,7 @@ def migrate_service_enabled(apps, schema_editor):
|
|||||||
app_config.models_module = True
|
app_config.models_module = True
|
||||||
create_permissions(app_config, apps=apps, verbosity=0)
|
create_permissions(app_config, apps=apps, verbosity=0)
|
||||||
app_config.models_module = None
|
app_config.models_module = None
|
||||||
|
|
||||||
Group = apps.get_model("auth", "Group")
|
Group = apps.get_model("auth", "Group")
|
||||||
Permission = apps.get_model("auth", "Permission")
|
Permission = apps.get_model("auth", "Permission")
|
||||||
Ips4User = apps.get_model("ips4", "Ips4User")
|
Ips4User = apps.get_model("ips4", "Ips4User")
|
||||||
|
|||||||
@ -5,12 +5,12 @@ from ...admin import ServicesUserAdmin
|
|||||||
|
|
||||||
|
|
||||||
@admin.register(MumbleUser)
|
@admin.register(MumbleUser)
|
||||||
class MumbleUserAdmin(ServicesUserAdmin):
|
class MumbleUserAdmin(ServicesUserAdmin):
|
||||||
list_display = ServicesUserAdmin.list_display + (
|
list_display = ServicesUserAdmin.list_display + (
|
||||||
'username',
|
'username',
|
||||||
'groups',
|
'groups',
|
||||||
)
|
)
|
||||||
search_fields = ServicesUserAdmin.search_fields + (
|
search_fields = ServicesUserAdmin.search_fields + (
|
||||||
'username',
|
'username',
|
||||||
'groups'
|
'groups'
|
||||||
)
|
)
|
||||||
|
|||||||
@ -44,7 +44,7 @@ class MumbleService(ServicesHook):
|
|||||||
logger.debug("Updating %s nickname for %s" % (self.name, user))
|
logger.debug("Updating %s nickname for %s" % (self.name, user))
|
||||||
if MumbleTasks.has_account(user):
|
if MumbleTasks.has_account(user):
|
||||||
MumbleTasks.update_display_name.apply_async(args=[user.pk], countdown=5) # cooldown on this task to ensure DB clean when syncing
|
MumbleTasks.update_display_name.apply_async(args=[user.pk], countdown=5) # cooldown on this task to ensure DB clean when syncing
|
||||||
|
|
||||||
def validate_user(self, user):
|
def validate_user(self, user):
|
||||||
if MumbleTasks.has_account(user) and not self.service_active_for_user(user):
|
if MumbleTasks.has_account(user) and not self.service_active_for_user(user):
|
||||||
self.delete_user(user, notify_user=True)
|
self.delete_user(user, notify_user=True)
|
||||||
|
|||||||
@ -18,11 +18,11 @@ class MumbleManager(models.Manager):
|
|||||||
def get_display_name(user):
|
def get_display_name(user):
|
||||||
from .auth_hooks import MumbleService
|
from .auth_hooks import MumbleService
|
||||||
return NameFormatter(MumbleService(), user).format_name()
|
return NameFormatter(MumbleService(), user).format_name()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_username(user):
|
def get_username(user):
|
||||||
return user.profile.main_character.character_name # main character as the user.username may be incorect
|
return user.profile.main_character.character_name # main character as the user.username may be incorect
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitise_username(username):
|
def sanitise_username(username):
|
||||||
return username.replace(" ", "_")
|
return username.replace(" ", "_")
|
||||||
|
|||||||
@ -6,6 +6,6 @@ from ...admin import ServicesUserAdmin
|
|||||||
|
|
||||||
@admin.register(OpenfireUser)
|
@admin.register(OpenfireUser)
|
||||||
class OpenfireUserAdmin(ServicesUserAdmin):
|
class OpenfireUserAdmin(ServicesUserAdmin):
|
||||||
list_display = ServicesUserAdmin.list_display + ('username',)
|
list_display = ServicesUserAdmin.list_display + ('username',)
|
||||||
search_fields = ServicesUserAdmin.search_fields + ('username', )
|
search_fields = ServicesUserAdmin.search_fields + ('username', )
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ def migrate_service_enabled(apps, schema_editor):
|
|||||||
app_config.models_module = True
|
app_config.models_module = True
|
||||||
create_permissions(app_config, apps=apps, verbosity=0)
|
create_permissions(app_config, apps=apps, verbosity=0)
|
||||||
app_config.models_module = None
|
app_config.models_module = None
|
||||||
|
|
||||||
Group = apps.get_model("auth", "Group")
|
Group = apps.get_model("auth", "Group")
|
||||||
Permission = apps.get_model("auth", "Permission")
|
Permission = apps.get_model("auth", "Permission")
|
||||||
OpenfireUser = apps.get_model("openfire", "OpenfireUser")
|
OpenfireUser = apps.get_model("openfire", "OpenfireUser")
|
||||||
|
|||||||
@ -5,5 +5,5 @@ from ...admin import ServicesUserAdmin
|
|||||||
|
|
||||||
@admin.register(Phpbb3User)
|
@admin.register(Phpbb3User)
|
||||||
class Phpbb3UserAdmin(ServicesUserAdmin):
|
class Phpbb3UserAdmin(ServicesUserAdmin):
|
||||||
list_display = ServicesUserAdmin.list_display + ('username',)
|
list_display = ServicesUserAdmin.list_display + ('username',)
|
||||||
search_fields = ServicesUserAdmin.search_fields + ('username', )
|
search_fields = ServicesUserAdmin.search_fields + ('username', )
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user