mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-05 06:36:19 +01:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f98b5350e | ||
|
|
9de4d557e3 | ||
|
|
1d5f2634f1 | ||
|
|
710d26d36d | ||
|
|
47793e6198 | ||
|
|
5fcb56a087 | ||
|
|
808080d5ee | ||
|
|
e6037f1680 | ||
|
|
5c3ded6b07 | ||
|
|
0c14e35d15 | ||
|
|
c13be5d39a | ||
|
|
e4b515c1d5 | ||
|
|
65e2c87e8f | ||
|
|
68ce25854a | ||
|
|
3df6643513 | ||
|
|
6ea0ebc9f9 | ||
|
|
26236f5886 | ||
|
|
1420c71ec5 | ||
|
|
5a2c9243c4 | ||
|
|
fecd748198 | ||
|
|
85351b2c66 | ||
|
|
8b3e5b6462 | ||
|
|
93af920b8f | ||
|
|
b1248d9845 | ||
|
|
c86abef07d | ||
|
|
17ad5dfe33 | ||
|
|
e1843fe1f1 | ||
|
|
256a21f058 | ||
|
|
1473259e41 | ||
|
|
e935b91e93 | ||
|
|
07258a6914 | ||
|
|
cb35808508 | ||
|
|
937d656227 | ||
|
|
75a3adb2c9 | ||
|
|
148e208476 | ||
|
|
0036e8b280 | ||
|
|
ea2b5bfecf | ||
|
|
aa7495fa60 | ||
|
|
162ec1bd86 | ||
|
|
2668884008 | ||
|
|
abdc3f3485 | ||
|
|
911f21ee7c | ||
|
|
2387c40254 | ||
|
|
76e18a79b3 | ||
|
|
9725c9c947 | ||
|
|
247ed7cc64 | ||
|
|
2fd2af793e | ||
|
|
3fc36b9ce1 | ||
|
|
c12fd2d7bc | ||
|
|
7fe1ba2fb2 | ||
|
|
ab7eb3e5df | ||
|
|
3452c3acd1 | ||
|
|
3c305fbf37 | ||
|
|
a5e0721ec1 | ||
|
|
164a0d5376 | ||
|
|
2bcf6ec39a | ||
|
|
40824156bf | ||
|
|
cec4495034 | ||
|
|
74eb8621d9 | ||
|
|
4394d25961 | ||
|
|
8113327d31 | ||
|
|
aeeb35bc60 | ||
|
|
630aa3f320 | ||
|
|
3487a945c2 | ||
|
|
1936ae44a3 | ||
|
|
3d7a84e786 | ||
|
|
a4d6730cb0 | ||
|
|
b724227a29 | ||
|
|
d72964fd7c | ||
|
|
d4a41cfb60 | ||
|
|
05859453df | ||
|
|
240d910c9b | ||
|
|
0c31bce7d0 | ||
|
|
f4c4ae36ed | ||
|
|
b9931b2ceb | ||
|
|
4fd6f06c0b | ||
|
|
09573ba7ef |
@@ -1,54 +1,94 @@
|
|||||||
stages:
|
stages:
|
||||||
|
- gitlab
|
||||||
- test
|
- test
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
|
include:
|
||||||
|
- template: Dependency-Scanning.gitlab-ci.yml
|
||||||
|
- template: Security/SAST.gitlab-ci.yml
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- apt-get update && apt-get install redis-server -y
|
- apt-get update && apt-get install redis-server -y
|
||||||
- redis-server --daemonize yes
|
- redis-server --daemonize yes
|
||||||
- redis-cli ping
|
- python -V
|
||||||
- python -V
|
- pip install wheel tox
|
||||||
- pip install wheel tox
|
|
||||||
|
sast:
|
||||||
|
stage: gitlab
|
||||||
|
before_script: []
|
||||||
|
|
||||||
|
dependency_scanning:
|
||||||
|
stage: gitlab
|
||||||
|
before_script:
|
||||||
|
- apt-get update && apt-get install redis-server libmariadbclient-dev -y
|
||||||
|
- redis-server --daemonize yes
|
||||||
|
- python -V
|
||||||
|
- pip install wheel tox
|
||||||
|
|
||||||
test-3.6-core:
|
test-3.6-core:
|
||||||
image: python:3.6-buster
|
image: python:3.6-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py36-core
|
- tox -e py36-core
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
cobertura: coverage.xml
|
||||||
|
|
||||||
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:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
cobertura: coverage.xml
|
||||||
|
|
||||||
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:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
cobertura: coverage.xml
|
||||||
|
|
||||||
test-3.6-all:
|
test-3.6-all:
|
||||||
image: python:3.6-buster
|
image: python:3.6-buster
|
||||||
script:
|
script:
|
||||||
- tox -e py36-all
|
- tox -e py36-all
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
cobertura: coverage.xml
|
||||||
|
|
||||||
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:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
cobertura: coverage.xml
|
||||||
|
|
||||||
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:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
cobertura: coverage.xml
|
||||||
|
|
||||||
deploy_production:
|
deploy_production:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: python:3.8-buster
|
image: python:3.8-buster
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- pip install twine
|
- pip install twine wheel
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- python setup.py sdist
|
- python setup.py sdist bdist_wheel
|
||||||
- twine upload dist/*
|
- twine upload dist/*
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_COMMIT_TAG
|
- if: $CI_COMMIT_TAG
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# This will make sure the app is always imported when
|
# This will make sure the app is always imported when
|
||||||
# Django starts so that shared_task will use this app.
|
# Django starts so that shared_task will use this app.
|
||||||
|
|
||||||
__version__ = '2.8.1'
|
__version__ = '2.8.5'
|
||||||
__title__ = 'Alliance Auth'
|
__title__ = 'Alliance Auth'
|
||||||
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
||||||
NAME = '%s v%s' % (__title__, __version__)
|
NAME = '%s v%s' % (__title__, __version__)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||||
from django.contrib.auth.models import User as BaseUser, \
|
from django.contrib.auth.models import User as BaseUser, \
|
||||||
Permission as BasePermission, Group
|
Permission as BasePermission, Group
|
||||||
from django.db.models import Q, F
|
from django.db.models import Count, Q
|
||||||
from allianceauth.services.hooks import ServicesHook
|
from allianceauth.services.hooks import ServicesHook
|
||||||
from django.db.models.signals import pre_save, post_save, pre_delete, \
|
from django.db.models.signals import pre_save, post_save, pre_delete, \
|
||||||
post_delete, m2m_changed
|
post_delete, m2m_changed
|
||||||
@@ -24,11 +22,6 @@ from allianceauth.eveonline.tasks import update_character
|
|||||||
from .app_settings import AUTHENTICATION_ADMIN_USERS_MAX_GROUPS, \
|
from .app_settings import AUTHENTICATION_ADMIN_USERS_MAX_GROUPS, \
|
||||||
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
|
||||||
_has_auto_groups = True
|
|
||||||
else:
|
|
||||||
_has_auto_groups = False
|
|
||||||
|
|
||||||
|
|
||||||
def make_service_hooks_update_groups_action(service):
|
def make_service_hooks_update_groups_action(service):
|
||||||
"""
|
"""
|
||||||
@@ -91,8 +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)
|
||||||
qs = EveCharacter.objects.filter(query)
|
|
||||||
formset = super().get_formset(request, obj=obj, **kwargs)
|
formset = super().get_formset(request, obj=obj, **kwargs)
|
||||||
|
|
||||||
def get_kwargs(self, index):
|
def get_kwargs(self, index):
|
||||||
@@ -121,6 +113,8 @@ def user_profile_pic(obj):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
user_profile_pic.short_description = ''
|
user_profile_pic.short_description = ''
|
||||||
|
|
||||||
|
|
||||||
@@ -152,6 +146,7 @@ def user_username(obj):
|
|||||||
user_obj.username,
|
user_obj.username,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
user_username.short_description = 'user / main'
|
user_username.short_description = 'user / main'
|
||||||
user_username.admin_order_field = 'username'
|
user_username.admin_order_field = 'username'
|
||||||
|
|
||||||
@@ -168,7 +163,8 @@ def user_main_organization(obj):
|
|||||||
else:
|
else:
|
||||||
corporation = user_obj.profile.main_character.corporation_name
|
corporation = user_obj.profile.main_character.corporation_name
|
||||||
if user_obj.profile.main_character.alliance_id:
|
if user_obj.profile.main_character.alliance_id:
|
||||||
result = format_html('{}<br>{}',
|
result = format_html(
|
||||||
|
'{}<br>{}',
|
||||||
corporation,
|
corporation,
|
||||||
user_obj.profile.main_character.alliance_name
|
user_obj.profile.main_character.alliance_name
|
||||||
)
|
)
|
||||||
@@ -176,6 +172,7 @@ def user_main_organization(obj):
|
|||||||
result = corporation
|
result = corporation
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
user_main_organization.short_description = 'Corporation / Alliance (Main)'
|
user_main_organization.short_description = 'Corporation / Alliance (Main)'
|
||||||
user_main_organization.admin_order_field = \
|
user_main_organization.admin_order_field = \
|
||||||
'profile__main_character__corporation_name'
|
'profile__main_character__corporation_name'
|
||||||
@@ -205,13 +202,13 @@ class MainCorporationsFilter(admin.SimpleListFilter):
|
|||||||
return qs.all()
|
return qs.all()
|
||||||
else:
|
else:
|
||||||
if qs.model == User:
|
if qs.model == User:
|
||||||
return qs\
|
return qs.filter(
|
||||||
.filter(profile__main_character__corporation_id=\
|
profile__main_character__corporation_id=self.value()
|
||||||
self.value())
|
)
|
||||||
else:
|
else:
|
||||||
return qs\
|
return qs.filter(
|
||||||
.filter(user__profile__main_character__corporation_id=\
|
user__profile__main_character__corporation_id=self.value()
|
||||||
self.value())
|
)
|
||||||
|
|
||||||
|
|
||||||
class MainAllianceFilter(admin.SimpleListFilter):
|
class MainAllianceFilter(admin.SimpleListFilter):
|
||||||
@@ -239,12 +236,11 @@ class MainAllianceFilter(admin.SimpleListFilter):
|
|||||||
return qs.all()
|
return qs.all()
|
||||||
else:
|
else:
|
||||||
if qs.model == User:
|
if qs.model == User:
|
||||||
return qs\
|
return qs.filter(profile__main_character__alliance_id=self.value())
|
||||||
.filter(profile__main_character__alliance_id=self.value())
|
|
||||||
else:
|
else:
|
||||||
return qs\
|
return qs.filter(
|
||||||
.filter(user__profile__main_character__alliance_id=\
|
user__profile__main_character__alliance_id=self.value()
|
||||||
self.value())
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_main_character_model(modeladmin, request, queryset):
|
def update_main_character_model(modeladmin, request, queryset):
|
||||||
@@ -259,6 +255,7 @@ def update_main_character_model(modeladmin, request, queryset):
|
|||||||
'Update from ESI started for {} characters'.format(tasks_count)
|
'Update from ESI started for {} characters'.format(tasks_count)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
update_main_character_model.short_description = \
|
update_main_character_model.short_description = \
|
||||||
'Update main character model from ESI'
|
'Update main character model from ESI'
|
||||||
|
|
||||||
@@ -267,32 +264,16 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
"""Extending Django's UserAdmin model
|
"""Extending Django's UserAdmin model
|
||||||
|
|
||||||
Behavior of groups and characters columns can be configured via settings
|
Behavior of groups and characters columns can be configured via settings
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
css = {
|
css = {
|
||||||
"all": ("authentication/css/admin.css",)
|
"all": ("authentication/css/admin.css",)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealGroupsFilter(admin.SimpleListFilter):
|
def get_queryset(self, request):
|
||||||
"""Custom filter to get groups w/o Autogroups"""
|
qs = super().get_queryset(request)
|
||||||
title = 'group'
|
return qs.prefetch_related("character_ownerships__character", "groups")
|
||||||
parameter_name = 'group_id__exact'
|
|
||||||
|
|
||||||
def lookups(self, request, model_admin):
|
|
||||||
qs = Group.objects.all().order_by(Lower('name'))
|
|
||||||
if _has_auto_groups:
|
|
||||||
qs = qs\
|
|
||||||
.filter(managedalliancegroup__isnull=True)\
|
|
||||||
.filter(managedcorpgroup__isnull=True)
|
|
||||||
return tuple([(x.pk, x.name) for x in qs])
|
|
||||||
|
|
||||||
def queryset(self, request, queryset):
|
|
||||||
if self.value() is None:
|
|
||||||
return queryset.all()
|
|
||||||
else:
|
|
||||||
return queryset.filter(groups__pk=self.value())
|
|
||||||
|
|
||||||
def get_actions(self, request):
|
def get_actions(self, request):
|
||||||
actions = super(BaseUserAdmin, self).get_actions(request)
|
actions = super(BaseUserAdmin, self).get_actions(request)
|
||||||
@@ -341,11 +322,9 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
inlines = BaseUserAdmin.inlines + [UserProfileInline]
|
inlines = BaseUserAdmin.inlines + [UserProfileInline]
|
||||||
|
ordering = ('username', )
|
||||||
ordering = ('username', )
|
list_select_related = ('profile__state', 'profile__main_character')
|
||||||
list_select_related = True
|
show_full_result_count = True
|
||||||
show_full_result_count = True
|
|
||||||
|
|
||||||
list_display = (
|
list_display = (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
@@ -358,10 +337,9 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
'_role'
|
'_role'
|
||||||
)
|
)
|
||||||
list_display_links = None
|
list_display_links = None
|
||||||
|
|
||||||
list_filter = (
|
list_filter = (
|
||||||
'profile__state',
|
'profile__state',
|
||||||
RealGroupsFilter,
|
'groups',
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
'is_active',
|
'is_active',
|
||||||
@@ -375,41 +353,25 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _characters(self, obj):
|
def _characters(self, obj):
|
||||||
my_characters = [
|
character_ownerships = list(obj.character_ownerships.all())
|
||||||
x.character.character_name
|
characters = [obj.character.character_name for obj in character_ownerships]
|
||||||
for x in CharacterOwnership.objects\
|
|
||||||
.filter(user=obj)\
|
|
||||||
.order_by('character__character_name')\
|
|
||||||
.select_related()
|
|
||||||
]
|
|
||||||
return self._list_2_html_w_tooltips(
|
return self._list_2_html_w_tooltips(
|
||||||
my_characters,
|
sorted(characters),
|
||||||
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
AUTHENTICATION_ADMIN_USERS_MAX_CHARS
|
||||||
)
|
)
|
||||||
|
|
||||||
_characters.short_description = 'characters'
|
_characters.short_description = 'characters'
|
||||||
|
|
||||||
|
|
||||||
def _state(self, obj):
|
def _state(self, obj):
|
||||||
return obj.profile.state.name
|
return obj.profile.state.name
|
||||||
|
|
||||||
_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):
|
||||||
if not _has_auto_groups:
|
my_groups = sorted([group.name for group in list(obj.groups.all())])
|
||||||
my_groups = [x.name for x in obj.groups.order_by('name')]
|
|
||||||
else:
|
|
||||||
my_groups = [
|
|
||||||
x.name for x in obj.groups\
|
|
||||||
.filter(managedalliancegroup__isnull=True)\
|
|
||||||
.filter(managedcorpgroup__isnull=True)\
|
|
||||||
.order_by('name')
|
|
||||||
]
|
|
||||||
|
|
||||||
return self._list_2_html_w_tooltips(
|
return self._list_2_html_w_tooltips(
|
||||||
my_groups,
|
my_groups, AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
||||||
AUTHENTICATION_ADMIN_USERS_MAX_GROUPS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_groups.short_description = 'groups'
|
_groups.short_description = 'groups'
|
||||||
@@ -437,7 +399,7 @@ class UserAdmin(BaseUserAdmin):
|
|||||||
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
||||||
"""overriding this formfield to have sorted lists in the form"""
|
"""overriding this formfield to have sorted lists in the form"""
|
||||||
if db_field.name == "groups":
|
if db_field.name == "groups":
|
||||||
kwargs["queryset"] = Group.objects.all().order_by(Lower('name'))
|
kwargs["queryset"] = Group.objects.all().order_by(Lower('name'))
|
||||||
return super().formfield_for_manytomany(db_field, request, **kwargs)
|
return super().formfield_for_manytomany(db_field, request, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@@ -446,9 +408,14 @@ class StateAdmin(admin.ModelAdmin):
|
|||||||
list_select_related = True
|
list_select_related = True
|
||||||
list_display = ('name', 'priority', '_user_count')
|
list_display = ('name', 'priority', '_user_count')
|
||||||
|
|
||||||
|
def get_queryset(self, request):
|
||||||
|
qs = super().get_queryset(request)
|
||||||
|
return qs.annotate(user_count=Count("userprofile__id"))
|
||||||
|
|
||||||
def _user_count(self, obj):
|
def _user_count(self, obj):
|
||||||
return obj.userprofile_set.all().count()
|
return obj.user_count
|
||||||
_user_count.short_description = 'Users'
|
_user_count.short_description = 'Users'
|
||||||
|
_user_count.admin_order_field = 'user_count'
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
@@ -471,7 +438,7 @@ class StateAdmin(admin.ModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
||||||
"""overriding this formfield to have sorted lists in the form"""
|
"""overriding this formfield to have sorted lists in the form"""
|
||||||
if db_field.name == "member_characters":
|
if db_field.name == "member_characters":
|
||||||
kwargs["queryset"] = EveCharacter.objects.all()\
|
kwargs["queryset"] = EveCharacter.objects.all()\
|
||||||
.order_by(Lower('character_name'))
|
.order_by(Lower('character_name'))
|
||||||
@@ -481,8 +448,10 @@ class StateAdmin(admin.ModelAdmin):
|
|||||||
elif db_field.name == "member_alliances":
|
elif db_field.name == "member_alliances":
|
||||||
kwargs["queryset"] = EveAllianceInfo.objects.all()\
|
kwargs["queryset"] = EveAllianceInfo.objects.all()\
|
||||||
.order_by(Lower('alliance_name'))
|
.order_by(Lower('alliance_name'))
|
||||||
|
elif db_field.name == "permissions":
|
||||||
|
kwargs["queryset"] = Permission.objects.select_related("content_type").all()
|
||||||
return super().formfield_for_manytomany(db_field, request, **kwargs)
|
return super().formfield_for_manytomany(db_field, request, **kwargs)
|
||||||
|
|
||||||
def has_delete_permission(self, request, obj=None):
|
def has_delete_permission(self, request, obj=None):
|
||||||
if obj == get_guest_state():
|
if obj == get_guest_state():
|
||||||
return False
|
return False
|
||||||
@@ -504,7 +473,8 @@ class BaseOwnershipAdmin(admin.ModelAdmin):
|
|||||||
"all": ("authentication/css/admin.css",)
|
"all": ("authentication/css/admin.css",)
|
||||||
}
|
}
|
||||||
|
|
||||||
list_select_related = True
|
list_select_related = (
|
||||||
|
'user__profile__state', 'user__profile__main_character', 'character')
|
||||||
list_display = (
|
list_display = (
|
||||||
user_profile_pic,
|
user_profile_pic,
|
||||||
user_username,
|
user_username,
|
||||||
@@ -542,6 +512,7 @@ class CharacterOwnershipAdmin(BaseOwnershipAdmin):
|
|||||||
class PermissionAdmin(admin.ModelAdmin):
|
class PermissionAdmin(admin.ModelAdmin):
|
||||||
actions = None
|
actions = None
|
||||||
readonly_fields = [field.name for field in BasePermission._meta.fields]
|
readonly_fields = [field.name for field in BasePermission._meta.fields]
|
||||||
|
search_fields = ('codename', )
|
||||||
list_display = ('admin_name', 'name', 'codename', 'content_type')
|
list_display = ('admin_name', 'name', 'codename', 'content_type')
|
||||||
list_filter = ('content_type__app_label',)
|
list_filter = ('content_type__app_label',)
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ def get_admin_change_view_url(obj: object) -> str:
|
|||||||
args=(obj.pk,)
|
args=(obj.pk,)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_admin_search_url(ModelClass: type) -> str:
|
def get_admin_search_url(ModelClass: type) -> str:
|
||||||
"""returns URL to search URL for model of given object"""
|
"""returns URL to search URL for model of given object"""
|
||||||
return '{}{}/'.format(
|
return '{}{}/'.format(
|
||||||
reverse('admin:app_list', args=(ModelClass._meta.app_label,)),
|
reverse('admin:app_list', args=(ModelClass._meta.app_label,)),
|
||||||
ModelClass.__name__.lower()
|
ModelClass.__name__.lower()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
from unittest.mock import patch, MagicMock
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from django.contrib.auth.models import User as BaseUser, Group
|
from django.contrib.auth.models import Group
|
||||||
from django.test import TestCase, RequestFactory, Client
|
from django.test import TestCase, RequestFactory, Client
|
||||||
|
|
||||||
from allianceauth.authentication.models import (
|
from allianceauth.authentication.models import (
|
||||||
@@ -18,8 +16,7 @@ from allianceauth.tests.auth_utils import AuthUtils
|
|||||||
|
|
||||||
from ..admin import (
|
from ..admin import (
|
||||||
BaseUserAdmin,
|
BaseUserAdmin,
|
||||||
CharacterOwnershipAdmin,
|
CharacterOwnershipAdmin,
|
||||||
PermissionAdmin,
|
|
||||||
StateAdmin,
|
StateAdmin,
|
||||||
MainCorporationsFilter,
|
MainCorporationsFilter,
|
||||||
MainAllianceFilter,
|
MainAllianceFilter,
|
||||||
@@ -35,11 +32,6 @@ from ..admin import (
|
|||||||
)
|
)
|
||||||
from . import get_admin_change_view_url, get_admin_search_url
|
from . import get_admin_change_view_url, get_admin_search_url
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
|
||||||
_has_auto_groups = True
|
|
||||||
from allianceauth.eveonline.autogroups.models import AutogroupsConfig
|
|
||||||
else:
|
|
||||||
_has_auto_groups = False
|
|
||||||
|
|
||||||
MODULE_PATH = 'allianceauth.authentication.admin'
|
MODULE_PATH = 'allianceauth.authentication.admin'
|
||||||
|
|
||||||
@@ -48,6 +40,7 @@ class MockRequest(object):
|
|||||||
def __init__(self, user=None):
|
def __init__(self, user=None):
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
|
|
||||||
class TestCaseWithTestData(TestCase):
|
class TestCaseWithTestData(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -279,6 +272,7 @@ class TestStateAdmin(TestCaseWithTestData):
|
|||||||
expected = 200
|
expected = 200
|
||||||
self.assertEqual(response.status_code, expected)
|
self.assertEqual(response.status_code, expected)
|
||||||
|
|
||||||
|
|
||||||
class TestUserAdmin(TestCaseWithTestData):
|
class TestUserAdmin(TestCaseWithTestData):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -287,24 +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 _create_autogroups(self):
|
|
||||||
"""create autogroups for corps and alliances"""
|
|
||||||
if _has_auto_groups:
|
|
||||||
autogroups_config = AutogroupsConfig(
|
|
||||||
corp_groups = True,
|
|
||||||
alliance_groups = True
|
|
||||||
)
|
|
||||||
autogroups_config.save()
|
|
||||||
for state in State.objects.all():
|
|
||||||
autogroups_config.states.add(state)
|
|
||||||
autogroups_config.update_corp_group_membership(self.user_1)
|
|
||||||
|
|
||||||
# column rendering
|
|
||||||
|
|
||||||
def test_user_profile_pic_u1(self):
|
def test_user_profile_pic_u1(self):
|
||||||
expected = ('<img src="https://images.evetech.net/characters/1001/'
|
expected = (
|
||||||
'portrait?size=32" class="img-circle">')
|
'<img src="https://images.evetech.net/characters/1001/'
|
||||||
|
'portrait?size=32" class="img-circle">'
|
||||||
|
)
|
||||||
self.assertEqual(user_profile_pic(self.user_1), expected)
|
self.assertEqual(user_profile_pic(self.user_1), expected)
|
||||||
|
|
||||||
def test_user_profile_pic_u3(self):
|
def test_user_profile_pic_u3(self):
|
||||||
@@ -351,37 +333,17 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
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):
|
||||||
self._create_autogroups()
|
|
||||||
expected = 'Group 1'
|
expected = 'Group 1'
|
||||||
result = self.modeladmin._groups(self.user_1)
|
result = self.modeladmin._groups(self.user_1)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_groups_u2(self):
|
def test_groups_u2(self):
|
||||||
self._create_autogroups()
|
|
||||||
expected = 'Group 2'
|
expected = 'Group 2'
|
||||||
result = self.modeladmin._groups(self.user_2)
|
result = self.modeladmin._groups(self.user_2)
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_groups_u3(self):
|
def test_groups_u3(self):
|
||||||
self._create_autogroups()
|
|
||||||
result = self.modeladmin._groups(self.user_3)
|
|
||||||
self.assertIsNone(result)
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_groups_u1_no_autogroups(self):
|
|
||||||
expected = 'Group 1'
|
|
||||||
result = self.modeladmin._groups(self.user_1)
|
|
||||||
self.assertEqual(result, expected)
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_groups_u2_no_autogroups(self):
|
|
||||||
expected = 'Group 2'
|
|
||||||
result = self.modeladmin._groups(self.user_2)
|
|
||||||
self.assertEqual(result, expected)
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_groups_u3_no_autogroups(self):
|
|
||||||
result = self.modeladmin._groups(self.user_3)
|
result = self.modeladmin._groups(self.user_3)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
@@ -413,8 +375,10 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
|
|
||||||
def test_list_2_html_w_tooltips_w_cutoff(self):
|
def test_list_2_html_w_tooltips_w_cutoff(self):
|
||||||
items = ['one', 'two', 'three']
|
items = ['one', 'two', 'three']
|
||||||
expected = ('<span data-tooltip="one, two, three" '
|
expected = (
|
||||||
'class="tooltip">one, two, (...)</span>')
|
'<span data-tooltip="one, two, three" '
|
||||||
|
'class="tooltip">one, two, (...)</span>'
|
||||||
|
)
|
||||||
result = self.modeladmin._list_2_html_w_tooltips(items, 2)
|
result = self.modeladmin._list_2_html_w_tooltips(items, 2)
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
@@ -439,63 +403,7 @@ class TestUserAdmin(TestCaseWithTestData):
|
|||||||
self.assertTrue(mock_message_user.called)
|
self.assertTrue(mock_message_user.called)
|
||||||
|
|
||||||
# filters
|
# filters
|
||||||
|
|
||||||
def test_filter_real_groups_with_autogroups(self):
|
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
|
||||||
list_filter = (UserAdmin.RealGroupsFilter,)
|
|
||||||
|
|
||||||
self._create_autogroups()
|
|
||||||
my_modeladmin = UserAdminTest(User, AdminSite())
|
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
|
||||||
request = self.factory.get('/')
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
filters = changelist.get_filters(request)
|
|
||||||
filterspec = filters[0][0]
|
|
||||||
expected = [
|
|
||||||
(self.group_1.pk, self.group_1.name),
|
|
||||||
(self.group_2.pk, self.group_2.name),
|
|
||||||
]
|
|
||||||
self.assertEqual(filterspec.lookup_choices, expected)
|
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
|
||||||
request = self.factory.get('/', {'group_id__exact': self.group_1.pk})
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
queryset = changelist.get_queryset(request)
|
|
||||||
expected = User.objects.filter(groups__in=[self.group_1])
|
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '._has_auto_groups', False)
|
|
||||||
def test_filter_real_groups_no_autogroups(self):
|
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
|
||||||
list_filter = (UserAdmin.RealGroupsFilter,)
|
|
||||||
|
|
||||||
my_modeladmin = UserAdminTest(User, AdminSite())
|
|
||||||
|
|
||||||
# Make sure the lookups are correct
|
|
||||||
request = self.factory.get('/')
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
filters = changelist.get_filters(request)
|
|
||||||
filterspec = filters[0][0]
|
|
||||||
expected = [
|
|
||||||
(self.group_1.pk, self.group_1.name),
|
|
||||||
(self.group_2.pk, self.group_2.name),
|
|
||||||
]
|
|
||||||
self.assertEqual(filterspec.lookup_choices, expected)
|
|
||||||
|
|
||||||
# Make sure the correct queryset is returned
|
|
||||||
request = self.factory.get('/', {'group_id__exact': self.group_1.pk})
|
|
||||||
request.user = self.user_1
|
|
||||||
changelist = my_modeladmin.get_changelist_instance(request)
|
|
||||||
queryset = changelist.get_queryset(request)
|
|
||||||
expected = User.objects.filter(groups__in=[self.group_1])
|
|
||||||
self.assertSetEqual(set(queryset), set(expected))
|
|
||||||
|
|
||||||
def test_filter_main_corporations(self):
|
def test_filter_main_corporations(self):
|
||||||
|
|
||||||
class UserAdminTest(BaseUserAdmin):
|
class UserAdminTest(BaseUserAdmin):
|
||||||
@@ -603,7 +511,6 @@ class TestMakeServicesHooksActions(TestCaseWithTestData):
|
|||||||
def sync_nicknames_bulk(self, user):
|
def sync_nicknames_bulk(self, user):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_service_has_update_groups_only(self):
|
def test_service_has_update_groups_only(self):
|
||||||
service = self.MyServicesHookTypeA()
|
service = self.MyServicesHookTypeA()
|
||||||
mock_service = MagicMock(spec=service)
|
mock_service = MagicMock(spec=service)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from math import ceil
|
from math import ceil
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from requests import RequestException
|
|
||||||
import requests_mock
|
import requests_mock
|
||||||
from packaging.version import Version as Pep440Version
|
from packaging.version import Version as Pep440Version
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from allianceauth.templatetags.admin_status import (
|
from allianceauth.templatetags.admin_status import (
|
||||||
@@ -12,8 +12,7 @@ from allianceauth.templatetags.admin_status import (
|
|||||||
_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,
|
||||||
_fetch_tags_from_gitlab,
|
|
||||||
_latests_versions
|
_latests_versions
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -103,35 +102,51 @@ class TestStatusOverviewTag(TestCase):
|
|||||||
|
|
||||||
class TestNotifications(TestCase):
|
class TestNotifications(TestCase):
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
cache.clear()
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_fetch_notification_issues_from_gitlab(self, requests_mocker):
|
def test_fetch_notification_issues_from_gitlab(self, requests_mocker):
|
||||||
|
# given
|
||||||
url = (
|
url = (
|
||||||
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
||||||
'?labels=announcement'
|
'?labels=announcement'
|
||||||
)
|
)
|
||||||
requests_mocker.get(url, json=GITHUB_NOTIFICATION_ISSUES)
|
requests_mocker.get(url, json=GITHUB_NOTIFICATION_ISSUES)
|
||||||
|
# when
|
||||||
result = _fetch_notification_issues_from_gitlab()
|
result = _fetch_notification_issues_from_gitlab()
|
||||||
|
# then
|
||||||
self.assertEqual(result, GITHUB_NOTIFICATION_ISSUES)
|
self.assertEqual(result, GITHUB_NOTIFICATION_ISSUES)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_notifications_normal(self, mock_cache):
|
def test_current_notifications_normal(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = GITHUB_NOTIFICATION_ISSUES
|
mock_cache.get_or_set.return_value = GITHUB_NOTIFICATION_ISSUES
|
||||||
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
|
# then
|
||||||
self.assertEqual(result['notifications'], GITHUB_NOTIFICATION_ISSUES[:5])
|
self.assertEqual(result['notifications'], GITHUB_NOTIFICATION_ISSUES[:5])
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@requests_mock.mock()
|
||||||
def test_current_notifications_failed(self, mock_cache):
|
def test_current_notifications_failed(self, requests_mocker):
|
||||||
mock_cache.get_or_set.side_effect = RequestException
|
# given
|
||||||
|
url = (
|
||||||
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
||||||
|
'?labels=announcement'
|
||||||
|
)
|
||||||
|
requests_mocker.get(url, status_code=404)
|
||||||
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
|
# then
|
||||||
self.assertEqual(result['notifications'], list())
|
self.assertEqual(result['notifications'], list())
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_notifications_is_none(self, mock_cache):
|
def test_current_notifications_is_none(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = None
|
mock_cache.get_or_set.return_value = None
|
||||||
|
# when
|
||||||
result = _current_notifications()
|
result = _current_notifications()
|
||||||
|
# then
|
||||||
self.assertEqual(result['notifications'], list())
|
self.assertEqual(result['notifications'], list())
|
||||||
|
|
||||||
|
|
||||||
@@ -143,12 +158,17 @@ class TestCeleryQueueLength(TestCase):
|
|||||||
|
|
||||||
class TestVersionTags(TestCase):
|
class TestVersionTags(TestCase):
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
cache.clear()
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_version_info_normal(self, mock_cache):
|
def test_current_version_info_normal(self, mock_cache):
|
||||||
|
# given
|
||||||
mock_cache.get_or_set.return_value = GITHUB_TAGS
|
mock_cache.get_or_set.return_value = GITHUB_TAGS
|
||||||
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
|
# then
|
||||||
self.assertTrue(result['latest_major'])
|
self.assertTrue(result['latest_major'])
|
||||||
self.assertTrue(result['latest_minor'])
|
self.assertTrue(result['latest_minor'])
|
||||||
self.assertTrue(result['latest_patch'])
|
self.assertTrue(result['latest_patch'])
|
||||||
@@ -158,32 +178,41 @@ class TestVersionTags(TestCase):
|
|||||||
self.assertEqual(result['latest_beta_version'], '2.4.6a1')
|
self.assertEqual(result['latest_beta_version'], '2.4.6a1')
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@requests_mock.mock()
|
||||||
def test_current_version_info_failed(self, mock_cache):
|
def test_current_version_info_failed(self, requests_mocker):
|
||||||
mock_cache.get_or_set.side_effect = RequestException
|
# given
|
||||||
|
url = (
|
||||||
expected = {}
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
||||||
|
'/repository/tags'
|
||||||
|
)
|
||||||
|
requests_mocker.get(url, status_code=500)
|
||||||
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
self.assertEqual(result, expected)
|
# then
|
||||||
|
self.assertEqual(result, {})
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
def test_fetch_tags_from_gitlab(self, requests_mocker):
|
def test_fetch_tags_from_gitlab(self, requests_mocker):
|
||||||
|
# given
|
||||||
url = (
|
url = (
|
||||||
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth'
|
||||||
'/repository/tags'
|
'/repository/tags'
|
||||||
)
|
)
|
||||||
requests_mocker.get(url, json=GITHUB_TAGS)
|
requests_mocker.get(url, json=GITHUB_TAGS)
|
||||||
result = _fetch_tags_from_gitlab()
|
# when
|
||||||
self.assertEqual(result, GITHUB_TAGS)
|
result = _current_version_summary()
|
||||||
|
# then
|
||||||
|
self.assertTrue(result)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
|
||||||
@patch(MODULE_PATH + '.admin_status.cache')
|
@patch(MODULE_PATH + '.admin_status.cache')
|
||||||
def test_current_version_info_return_no_data(self, mock_cache):
|
def test_current_version_info_return_no_data(self, mock_cache):
|
||||||
mock_cache.get_or_set.return_value = None
|
# given
|
||||||
|
mock_cache.get_or_set.return_value = None
|
||||||
expected = {}
|
# when
|
||||||
result = _current_version_summary()
|
result = _current_version_summary()
|
||||||
self.assertEqual(result, expected)
|
# then
|
||||||
|
self.assertEqual(result, {})
|
||||||
|
|
||||||
|
|
||||||
class TestLatestsVersion(TestCase):
|
class TestLatestsVersion(TestCase):
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ from django.contrib.auth import login, authenticate
|
|||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.http import JsonResponse
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from allianceauth.eveonline.models import EveCharacter
|
from allianceauth.eveonline.models import EveCharacter
|
||||||
|
|||||||
@@ -96,24 +96,62 @@ class EveAllianceForm(EveEntityForm):
|
|||||||
|
|
||||||
@admin.register(EveCorporationInfo)
|
@admin.register(EveCorporationInfo)
|
||||||
class EveCorporationInfoAdmin(admin.ModelAdmin):
|
class EveCorporationInfoAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ['corporation_name']
|
||||||
|
list_display = ('corporation_name', 'alliance')
|
||||||
|
list_select_related = ('alliance',)
|
||||||
|
list_filter = (('alliance', admin.RelatedOnlyFieldListFilter),)
|
||||||
|
ordering = ('corporation_name',)
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
if not obj or not obj.pk:
|
if not obj or not obj.pk:
|
||||||
return EveCorporationForm
|
return EveCorporationForm
|
||||||
return super(EveCorporationInfoAdmin, self).get_form(request, obj=obj, **kwargs)
|
return super().get_form(request, obj=obj, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(EveAllianceInfo)
|
@admin.register(EveAllianceInfo)
|
||||||
class EveAllianceInfoAdmin(admin.ModelAdmin):
|
class EveAllianceInfoAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ['alliance_name']
|
||||||
|
list_display = ('alliance_name',)
|
||||||
|
ordering = ('alliance_name',)
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
if not obj or not obj.pk:
|
if not obj or not obj.pk:
|
||||||
return EveAllianceForm
|
return EveAllianceForm
|
||||||
return super(EveAllianceInfoAdmin, self).get_form(request, obj=obj, **kwargs)
|
return super().get_form(request, obj=obj, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(EveCharacter)
|
@admin.register(EveCharacter)
|
||||||
class EveCharacterAdmin(admin.ModelAdmin):
|
class EveCharacterAdmin(admin.ModelAdmin):
|
||||||
search_fields = ['character_name', 'corporation_name', 'alliance_name', 'character_ownership__user__username']
|
search_fields = [
|
||||||
list_display = ('character_name', 'corporation_name', 'alliance_name', 'user', 'main_character')
|
'character_name',
|
||||||
|
'corporation_name',
|
||||||
|
'alliance_name',
|
||||||
|
'character_ownership__user__username'
|
||||||
|
]
|
||||||
|
list_display = (
|
||||||
|
'character_name', 'corporation_name', 'alliance_name', 'user', 'main_character'
|
||||||
|
)
|
||||||
|
list_select_related = (
|
||||||
|
'character_ownership', 'character_ownership__user__profile__main_character'
|
||||||
|
)
|
||||||
|
list_filter = (
|
||||||
|
'corporation_name',
|
||||||
|
'alliance_name',
|
||||||
|
(
|
||||||
|
'character_ownership__user__profile__main_character',
|
||||||
|
admin.RelatedOnlyFieldListFilter
|
||||||
|
),
|
||||||
|
)
|
||||||
|
ordering = ('character_name', )
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def user(obj):
|
def user(obj):
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ class EveCharacterManager(models.Manager):
|
|||||||
def update_character(self, character_id):
|
def update_character(self, character_id):
|
||||||
return self.get(character_id=character_id).update_character()
|
return self.get(character_id=character_id).update_character()
|
||||||
|
|
||||||
def get_character_by_id(self, char_id):
|
def get_character_by_id(self, character_id: int):
|
||||||
if self.filter(character_id=char_id).exists():
|
"""Return character by character ID or None if not found."""
|
||||||
return self.get(character_id=char_id)
|
try:
|
||||||
return None
|
return self.get(character_id=character_id)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class EveAllianceProviderManager:
|
class EveAllianceProviderManager:
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.1.1 on 2021-01-05 14:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('eveonline', '0012_index_additions'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='evecorporationinfo',
|
||||||
|
name='ceo_id',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
17
allianceauth/eveonline/migrations/0014_auto_20210105_1413.py
Normal file
17
allianceauth/eveonline/migrations/0014_auto_20210105_1413.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 3.1.1 on 2021-01-05 14:13
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('eveonline', '0013_evecorporationinfo_ceo_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='evecorporationinfo',
|
||||||
|
index=models.Index(fields=['ceo_id'], name='eveonline_e_ceo_id_eea7b8_idx'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -82,6 +82,7 @@ class EveCorporationInfo(models.Model):
|
|||||||
corporation_name = models.CharField(max_length=254, unique=True)
|
corporation_name = models.CharField(max_length=254, unique=True)
|
||||||
corporation_ticker = models.CharField(max_length=254)
|
corporation_ticker = models.CharField(max_length=254)
|
||||||
member_count = models.IntegerField()
|
member_count = models.IntegerField()
|
||||||
|
ceo_id = models.PositiveIntegerField(blank=True, null=True, default=None)
|
||||||
alliance = models.ForeignKey(
|
alliance = models.ForeignKey(
|
||||||
EveAllianceInfo, blank=True, null=True, on_delete=models.SET_NULL
|
EveAllianceInfo, blank=True, null=True, on_delete=models.SET_NULL
|
||||||
)
|
)
|
||||||
@@ -89,10 +90,16 @@ class EveCorporationInfo(models.Model):
|
|||||||
objects = EveCorporationManager()
|
objects = EveCorporationManager()
|
||||||
provider = EveCorporationProviderManager()
|
provider = EveCorporationProviderManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
indexes = [
|
||||||
|
models.Index(fields=['ceo_id',]),
|
||||||
|
]
|
||||||
|
|
||||||
def update_corporation(self, corp: providers.Corporation = None):
|
def update_corporation(self, corp: providers.Corporation = None):
|
||||||
if corp is None:
|
if corp is None:
|
||||||
corp = self.provider.get_corporation(self.corporation_id)
|
corp = self.provider.get_corporation(self.corporation_id)
|
||||||
self.member_count = corp.members
|
self.member_count = corp.members
|
||||||
|
self.ceo_id = corp.ceo_id
|
||||||
try:
|
try:
|
||||||
self.alliance = EveAllianceInfo.objects.get(alliance_id=corp.alliance_id)
|
self.alliance = EveAllianceInfo.objects.get(alliance_id=corp.alliance_id)
|
||||||
except EveAllianceInfo.DoesNotExist:
|
except EveAllianceInfo.DoesNotExist:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from django.conf import settings
|
from django.apps import apps
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.models import Group as BaseGroup, User
|
from django.contrib.auth.models import Group as BaseGroup, User
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
@@ -10,9 +10,8 @@ from django.dispatch import receiver
|
|||||||
|
|
||||||
from .models import AuthGroup
|
from .models import AuthGroup
|
||||||
from .models import GroupRequest
|
from .models import GroupRequest
|
||||||
from . import signals
|
|
||||||
|
|
||||||
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
|
if 'eve_autogroups' in apps.app_configs:
|
||||||
_has_auto_groups = True
|
_has_auto_groups = True
|
||||||
else:
|
else:
|
||||||
_has_auto_groups = False
|
_has_auto_groups = False
|
||||||
@@ -97,9 +96,9 @@ class HasLeaderFilter(admin.SimpleListFilter):
|
|||||||
else:
|
else:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
class GroupAdmin(admin.ModelAdmin):
|
|
||||||
list_select_related = True
|
class GroupAdmin(admin.ModelAdmin):
|
||||||
ordering = ('name', )
|
ordering = ('name',)
|
||||||
list_display = (
|
list_display = (
|
||||||
'name',
|
'name',
|
||||||
'_description',
|
'_description',
|
||||||
@@ -118,9 +117,12 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
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:
|
||||||
|
qs = qs.prefetch_related('managedalliancegroup_set', 'managedcorpgroup_set')
|
||||||
|
qs = qs.prefetch_related('authgroup__group_leaders').select_related('authgroup')
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
member_count=Count('user', distinct=True),
|
member_count=Count('user', distinct=True),
|
||||||
)
|
)
|
||||||
@@ -166,6 +168,11 @@ class GroupAdmin(admin.ModelAdmin):
|
|||||||
filter_horizontal = ('permissions',)
|
filter_horizontal = ('permissions',)
|
||||||
inlines = (AuthGroupInlineAdmin,)
|
inlines = (AuthGroupInlineAdmin,)
|
||||||
|
|
||||||
|
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
||||||
|
if db_field.name == "permissions":
|
||||||
|
kwargs["queryset"] = Permission.objects.select_related("content_type").all()
|
||||||
|
return super().formfield_for_manytomany(db_field, request, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Group(BaseGroup):
|
class Group(BaseGroup):
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -173,13 +180,29 @@ class Group(BaseGroup):
|
|||||||
verbose_name = BaseGroup._meta.verbose_name
|
verbose_name = BaseGroup._meta.verbose_name
|
||||||
verbose_name_plural = BaseGroup._meta.verbose_name_plural
|
verbose_name_plural = BaseGroup._meta.verbose_name_plural
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
admin.site.unregister(BaseGroup)
|
admin.site.unregister(BaseGroup)
|
||||||
finally:
|
finally:
|
||||||
admin.site.register(Group, GroupAdmin)
|
admin.site.register(Group, GroupAdmin)
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(GroupRequest)
|
@admin.register(GroupRequest)
|
||||||
|
class GroupRequestAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ('user__username', )
|
||||||
|
list_display = ('id', 'group', 'user', '_leave_request', 'status')
|
||||||
|
list_filter = (
|
||||||
|
('group', admin.RelatedOnlyFieldListFilter),
|
||||||
|
('user', admin.RelatedOnlyFieldListFilter),
|
||||||
|
'leave_request',
|
||||||
|
'status'
|
||||||
|
)
|
||||||
|
|
||||||
|
def _leave_request(self, obj) -> True:
|
||||||
|
return obj.leave_request
|
||||||
|
|
||||||
|
_leave_request.short_description = 'is leave request'
|
||||||
|
_leave_request.boolean = True
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_save, sender=Group)
|
@receiver(pre_save, sender=Group)
|
||||||
|
|||||||
@@ -5,3 +5,6 @@ class GroupManagementConfig(AppConfig):
|
|||||||
name = 'allianceauth.groupmanagement'
|
name = 'allianceauth.groupmanagement'
|
||||||
label = 'groupmanagement'
|
label = 'groupmanagement'
|
||||||
verbose_name = 'Group Management'
|
verbose_name = 'Group Management'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
from . import signals # noqa: F401
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
from allianceauth.authentication.signals import state_changed
|
|
||||||
from .managers import GroupManager
|
|
||||||
from .models import Group
|
|
||||||
from django.dispatch import receiver
|
|
||||||
import logging
|
import logging
|
||||||
|
from django.dispatch import receiver
|
||||||
|
from allianceauth.authentication.signals import state_changed
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@receiver(state_changed)
|
@receiver(state_changed)
|
||||||
def check_groups_on_state_change(sender, user, state, **kwargs):
|
def check_groups_on_state_change(sender, user, state, **kwargs):
|
||||||
logger.debug("Updating auth groups for {}".format(user))
|
logger.debug(
|
||||||
visible_groups = GroupManager.get_joinable_groups(state)
|
"Checking group memberships for %s based on new state %s" % (user, state)
|
||||||
visible_groups = visible_groups | Group.objects.select_related('authgroup').filter(authgroup__internal=True)
|
)
|
||||||
groups = user.groups.all()
|
state_groups = (
|
||||||
for g in groups:
|
user.groups.select_related("authgroup").exclude(authgroup__states=None)
|
||||||
if g not in visible_groups:
|
)
|
||||||
user.groups.remove(g)
|
for group in state_groups:
|
||||||
|
if not group.authgroup.states.filter(id=state.id).exists():
|
||||||
|
logger.info(
|
||||||
|
"Removing user %s from group %s due to missing state" % (user, group)
|
||||||
|
)
|
||||||
|
user.groups.remove(group)
|
||||||
|
|||||||
@@ -40,120 +40,121 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="panel panel-default panel-tabs-aa">
|
||||||
<div id="add" class="tab-pane fade in active panel panel-default">
|
<div class="panel-body">
|
||||||
<div class="panel-body">
|
<div class="tab-content">
|
||||||
{% if acceptrequests %}
|
|
||||||
<div class="table-responsive">
|
<div id="add" class="tab-pane active">
|
||||||
<table class="table table-aa">
|
{% if acceptrequests %}
|
||||||
<thead>
|
<div class="table-responsive">
|
||||||
<tr>
|
<table class="table table-aa">
|
||||||
<th>{% trans "Character" %}</th>
|
<thead>
|
||||||
<th>{% trans "Organization" %}</th>
|
|
||||||
<th>{% trans "Group" %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{% for acceptrequest in acceptrequests %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<th>{% trans "Character" %}</th>
|
||||||
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
<th>{% trans "Organization" %}</th>
|
||||||
{% if acceptrequest.main_char %}
|
<th>{% trans "Group" %}</th>
|
||||||
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
|
<th></th>
|
||||||
{{ acceptrequest.main_char.character_name }}
|
|
||||||
</a>
|
|
||||||
{% else %}
|
|
||||||
{{ acceptrequest.user.username }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if acceptrequest.main_char %}
|
|
||||||
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
|
|
||||||
{{ acceptrequest.main_char.corporation_name }}
|
|
||||||
</a><br>
|
|
||||||
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
|
|
||||||
{% else %}
|
|
||||||
{% trans "(unknown)" %}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>{{ acceptrequest.group.name }}</td>
|
|
||||||
<td class="text-right">
|
|
||||||
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
|
|
||||||
{% trans "Accept" %}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
|
|
||||||
{% trans "Reject" %}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
</thead>
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="leave" class="tab-pane fade panel panel-default">
|
<tbody>
|
||||||
<div class="panel-body">
|
{% for acceptrequest in acceptrequests %}
|
||||||
{% if leaverequests %}
|
<tr>
|
||||||
<div class="table-responsive">
|
<td>
|
||||||
<table class="table table-aa">
|
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
||||||
<thead>
|
{% if acceptrequest.main_char %}
|
||||||
<tr>
|
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
|
||||||
<th>{% trans "Character" %}</th>
|
{{ acceptrequest.main_char.character_name }}
|
||||||
<th>{% trans "Organization" %}</th>
|
</a>
|
||||||
<th>{% trans "Group" %}</th>
|
{% else %}
|
||||||
<th></th>
|
{{ acceptrequest.user.username }}
|
||||||
</tr>
|
{% endif %}
|
||||||
</thead>
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if acceptrequest.main_char %}
|
||||||
|
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
|
||||||
|
{{ acceptrequest.main_char.corporation_name }}
|
||||||
|
</a><br>
|
||||||
|
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
|
||||||
|
{% else %}
|
||||||
|
{% trans "(unknown)" %}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{ acceptrequest.group.name }}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
|
||||||
|
{% trans "Accept" %}
|
||||||
|
</a>
|
||||||
|
|
||||||
<tbody>
|
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
|
||||||
{% for leaverequest in leaverequests %}
|
{% trans "Reject" %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="leave" class="tab-pane">
|
||||||
|
{% if leaverequests %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-aa">
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<th>{% trans "Character" %}</th>
|
||||||
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
<th>{% trans "Organization" %}</th>
|
||||||
{% if leaverequest.main_char %}
|
<th>{% trans "Group" %}</th>
|
||||||
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
|
<th></th>
|
||||||
{{ leaverequest.main_char.character_name }}
|
|
||||||
</a>
|
|
||||||
{% else %}
|
|
||||||
{{ leaverequest.user.username }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if leaverequest.main_char %}
|
|
||||||
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
|
|
||||||
{{ leaverequest.main_char.corporation_name }}
|
|
||||||
</a><br>
|
|
||||||
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
|
|
||||||
{% else %}
|
|
||||||
{% trans "(unknown)" %}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>{{ leaverequest.group.name }}</td>
|
|
||||||
<td class="text-right">
|
|
||||||
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
|
|
||||||
{% trans "Accept" %}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
|
|
||||||
{% trans "Reject" %}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
</thead>
|
||||||
</tbody>
|
|
||||||
</table>
|
<tbody>
|
||||||
</div>
|
{% for leaverequest in leaverequests %}
|
||||||
{% else %}
|
<tr>
|
||||||
<div class="alert alert-warning text-center">{% trans "No group leave requests." %}</div>
|
<td>
|
||||||
{% endif %}
|
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
||||||
|
{% if leaverequest.main_char %}
|
||||||
|
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
|
||||||
|
{{ leaverequest.main_char.character_name }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{{ leaverequest.user.username }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if leaverequest.main_char %}
|
||||||
|
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
|
||||||
|
{{ leaverequest.main_char.corporation_name }}
|
||||||
|
</a><br>
|
||||||
|
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
|
||||||
|
{% else %}
|
||||||
|
{% trans "(unknown)" %}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{ leaverequest.group.name }}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
|
||||||
|
{% trans "Accept" %}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
|
||||||
|
{% trans "Reject" %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-warning text-center">{% trans "No group leave requests." %}</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,61 +1,100 @@
|
|||||||
from unittest import mock
|
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
|
|
||||||
from allianceauth.eveonline.models import EveCorporationInfo, EveAllianceInfo
|
from allianceauth.eveonline.models import EveCorporationInfo
|
||||||
|
from allianceauth.eveonline.autogroups.models import AutogroupsConfig
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
from ..signals import check_groups_on_state_change
|
|
||||||
|
|
||||||
|
class TestCheckGroupsOnStateChange(TestCase):
|
||||||
class GroupManagementStateTestCase(TestCase):
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user = AuthUtils.create_user('test')
|
cls.user = AuthUtils.create_user('test')
|
||||||
AuthUtils.add_main_character(
|
cls.character = AuthUtils.add_main_character_2(
|
||||||
cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='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.alliance = EveAllianceInfo.objects.create(
|
cls.corp_1 = EveCorporationInfo.objects.create(
|
||||||
alliance_id='3', alliance_name='test alliance', alliance_ticker='TEST', executor_corp_id='2'
|
corporation_id=2001, corporation_name='test corp 1', corporation_ticker='C1', member_count=1
|
||||||
)
|
)
|
||||||
cls.corp = EveCorporationInfo.objects.create(
|
cls.corp_2 = EveCorporationInfo.objects.create(
|
||||||
corporation_id='2', corporation_name='test corp', corporation_ticker='TEST', alliance=cls.alliance, member_count=1
|
corporation_id=2002, corporation_name='test corp 2', corporation_ticker='C2', member_count=1
|
||||||
)
|
)
|
||||||
cls.state_group = Group.objects.create(name='state_group')
|
cls.guest_state = AuthUtils.get_guest_state()
|
||||||
cls.open_group = Group.objects.create(name='open_group')
|
cls.test_state_1 = AuthUtils.create_state('test_state_1', 500)
|
||||||
cls.state = AuthUtils.create_state('test state', 500)
|
cls.test_state_2 = AuthUtils.create_state('test_state_2', 600)
|
||||||
cls.state_group.authgroup.states.add(cls.state)
|
|
||||||
cls.state_group.authgroup.internal = False
|
|
||||||
cls.state_group.save()
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
self.state.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 _refresh_test_group(self):
|
|
||||||
self.state_group = Group.objects.get(pk=self.state_group.pk)
|
|
||||||
|
|
||||||
def test_drop_state_group(self):
|
def test_drop_state_group(self):
|
||||||
self.user.groups.add(self.open_group)
|
"""
|
||||||
self.user.groups.add(self.state_group)
|
given user is member of: state group, normal group and auto group
|
||||||
self.assertEqual(self.user.profile.state.name, "Guest")
|
when user looses state
|
||||||
|
then user is automatically kicked from state group
|
||||||
self.state.member_corporations.add(self.corp)
|
and remains member of normal group and auto group
|
||||||
|
"""
|
||||||
|
# setup
|
||||||
|
state_group = Group.objects.create(name='state_group')
|
||||||
|
state_group.authgroup.states.add(self.test_state_1)
|
||||||
|
state_group.authgroup.internal = False
|
||||||
|
state_group.save()
|
||||||
|
normal_group = Group.objects.create(name='normal_group')
|
||||||
|
normal_group.authgroup.internal = False
|
||||||
|
normal_group.save()
|
||||||
|
internal_group = Group.objects.create(name='internal_group')
|
||||||
|
autogroup_config = AutogroupsConfig.objects.create(corp_groups=True)
|
||||||
|
autogroup_config.states.add(self.test_state_1)
|
||||||
|
autogroup_config.states.add(self.guest_state)
|
||||||
|
auto_group = autogroup_config.corp_managed_groups.first()
|
||||||
|
internal_state_group = Group.objects.create(name='internal_state_group')
|
||||||
|
internal_state_group.authgroup.states.add(self.test_state_1)
|
||||||
|
self.test_state_1.member_corporations.add(self.corp_1)
|
||||||
|
self.user.groups.add(normal_group)
|
||||||
|
self.user.groups.add(internal_group)
|
||||||
|
self.user.groups.add(state_group)
|
||||||
|
self.user.groups.add(internal_state_group)
|
||||||
|
|
||||||
|
# user changes state back to guest
|
||||||
|
self.test_state_1.member_corporations.clear()
|
||||||
|
|
||||||
|
# assert
|
||||||
self._refresh_user()
|
self._refresh_user()
|
||||||
self.assertEqual(self.user.profile.state, self.state)
|
self.assertEqual(self.user.profile.state, self.guest_state)
|
||||||
groups = self.user.groups.all()
|
groups = self.user.groups.all()
|
||||||
self.assertIn(self.state_group, groups) #keeps group
|
self.assertNotIn(state_group, groups) # looses state group
|
||||||
self.assertIn(self.open_group, groups) #public group unafected
|
self.assertNotIn(internal_state_group, groups) # looses state group
|
||||||
|
self.assertIn(normal_group, groups) # normal group unafected
|
||||||
|
self.assertIn(internal_group, groups) # internal group unafected
|
||||||
|
self.assertIn(auto_group, groups) # auto group unafected
|
||||||
|
|
||||||
self.state.member_corporations.clear()
|
def test_change_to_other_state(self):
|
||||||
|
"""
|
||||||
|
given a state group with 2 allowed states
|
||||||
|
when user changes from one state to the other
|
||||||
|
then user remains member of that group
|
||||||
|
"""
|
||||||
|
# setup
|
||||||
|
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_2)
|
||||||
|
|
||||||
|
self.test_state_1.member_corporations.add(self.corp_1)
|
||||||
|
self.test_state_2.member_corporations.add(self.corp_2)
|
||||||
|
self.user.groups.add(state_group)
|
||||||
|
|
||||||
|
# user changes state back to guest
|
||||||
|
self.character.corporation_id = 2002
|
||||||
|
self.character.corporation_name = "test corp 2"
|
||||||
|
self.character.save()
|
||||||
|
|
||||||
|
# assert
|
||||||
self._refresh_user()
|
self._refresh_user()
|
||||||
self.assertEqual(self.user.profile.state.name, "Guest")
|
self.assertEqual(self.user.profile.state, self.test_state_2)
|
||||||
groups = self.user.groups.all()
|
groups = self.user.groups.all()
|
||||||
self.assertNotIn(self.state_group, groups) #looses group
|
self.assertIn(state_group, groups)
|
||||||
self.assertIn(self.open_group, groups) #public group unafected
|
|
||||||
@@ -356,6 +356,9 @@ def group_request_add(request, group_id):
|
|||||||
if group.authgroup.open:
|
if group.authgroup.open:
|
||||||
logger.info("%s joining %s as is an open group" % (request.user, group))
|
logger.info("%s joining %s as is an open group" % (request.user, group))
|
||||||
request.user.groups.add(group)
|
request.user.groups.add(group)
|
||||||
|
request_info = request.user.username + ":" + group.name
|
||||||
|
log = RequestLog(request_type=False, group=group, request_info=request_info, action=1, request_actor=request.user)
|
||||||
|
log.save()
|
||||||
return redirect("groupmanagement:groups")
|
return redirect("groupmanagement:groups")
|
||||||
req = GroupRequest.objects.filter(user=request.user, group=group)
|
req = GroupRequest.objects.filter(user=request.user, group=group)
|
||||||
if len(req) > 0:
|
if len(req) > 0:
|
||||||
@@ -389,6 +392,9 @@ def group_request_leave(request, group_id):
|
|||||||
return redirect('groupmanagement:groups')
|
return redirect('groupmanagement:groups')
|
||||||
if group.authgroup.open:
|
if group.authgroup.open:
|
||||||
logger.info("%s leaving %s as is an open group" % (request.user, group))
|
logger.info("%s leaving %s as is an open group" % (request.user, group))
|
||||||
|
request_info = request.user.username + ":" + group.name
|
||||||
|
log = RequestLog(request_type=True, group=group, request_info=request_info, action=1, request_actor=request.user)
|
||||||
|
log.save()
|
||||||
request.user.groups.remove(group)
|
request.user.groups.remove(group)
|
||||||
return redirect("groupmanagement:groups")
|
return redirect("groupmanagement:groups")
|
||||||
req = GroupRequest.objects.filter(user=request.user, group=group)
|
req = GroupRequest.objects.filter(user=request.user, group=group)
|
||||||
@@ -398,6 +404,9 @@ def group_request_leave(request, group_id):
|
|||||||
return redirect("groupmanagement:groups")
|
return redirect("groupmanagement:groups")
|
||||||
if getattr(settings, 'AUTO_LEAVE', False):
|
if getattr(settings, 'AUTO_LEAVE', False):
|
||||||
logger.info("%s leaving joinable group %s due to auto_leave" % (request.user, group))
|
logger.info("%s leaving joinable group %s due to auto_leave" % (request.user, group))
|
||||||
|
request_info = request.user.username + ":" + group.name
|
||||||
|
log = RequestLog(request_type=True, group=group, request_info=request_info, action=1, request_actor=request.user)
|
||||||
|
log.save()
|
||||||
request.user.groups.remove(group)
|
request.user.groups.remove(group)
|
||||||
return redirect('groupmanagement:groups')
|
return redirect('groupmanagement:groups')
|
||||||
grouprequest = GroupRequest()
|
grouprequest = GroupRequest()
|
||||||
|
|||||||
Binary file not shown.
@@ -13,7 +13,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Peter Pfeufer <rounon.dax@terra-nanotech.de>, 2020\n"
|
"Last-Translator: Peter Pfeufer <rounon.dax@terra-nanotech.de>, 2020\n"
|
||||||
"Language-Team: German (https://www.transifex.com/alliance-auth/teams/107430/de/)\n"
|
"Language-Team: German (https://www.transifex.com/alliance-auth/teams/107430/de/)\n"
|
||||||
@@ -82,7 +82,7 @@ msgstr "Charaktere"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -168,11 +168,11 @@ msgstr ""
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "Authentifizierung mit dem ausgewählten Charakter nicht möglich."
|
msgstr "Authentifizierung mit dem ausgewählten Charakter nicht möglich."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "Token zur Registrierung ist abgelaufen."
|
msgstr "Token zur Registrierung ist abgelaufen."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
@@ -180,13 +180,13 @@ msgstr ""
|
|||||||
"Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur "
|
"Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur "
|
||||||
"Bestätigung."
|
"Bestätigung."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren."
|
"Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "Registrierung von neuen Konten ist zur Zeit nicht erlaubt."
|
msgstr "Registrierung von neuen Konten ist zur Zeit nicht erlaubt."
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
@@ -234,16 +234,16 @@ msgstr "Letzes Update:"
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "Charakter"
|
msgstr "Charakter"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -552,36 +552,35 @@ msgstr "Flottenteilnahme registriert."
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "FAT-Link ist abgelaufen."
|
msgstr "FAT-Link ist abgelaufen."
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr "Gruppenverwaltung"
|
msgstr "Gruppenverwaltung"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr "Protokoll"
|
msgstr "Protokoll"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Zurück"
|
msgstr "Zurück"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "Datum/Uhrzeit"
|
msgstr "Datum/Uhrzeit"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr "Antragsteller"
|
msgstr "Antragsteller"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Typ"
|
msgstr "Typ"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -592,11 +591,19 @@ msgstr "Typ"
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr "Aktion"
|
msgstr "Aktion"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr "Ausführender"
|
msgstr "Ausführender"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr "Entfernt"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr "Alle angezeigten Zeiten sind EVE/UTC"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "Keine Einträge für diese Gruppe gefunden."
|
msgstr "Keine Einträge für diese Gruppe gefunden."
|
||||||
|
|
||||||
@@ -604,22 +611,24 @@ msgstr "Keine Einträge für diese Gruppe gefunden."
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr "Gruppenmitglieder"
|
msgstr "Gruppenmitglieder"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr "Portrait"
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "Organization"
|
msgstr "Organization"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr "(unbekannt)"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "Aus Gruppe entfernen"
|
msgstr "Aus Gruppe entfernen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "Keine Gruppenmitglieder vorhanden."
|
msgstr "Keine Gruppenmitglieder vorhanden."
|
||||||
|
|
||||||
@@ -627,18 +636,18 @@ msgstr "Keine Gruppenmitglieder vorhanden."
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr "Gruppenmitgliedschaft"
|
msgstr "Gruppenmitgliedschaft"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Gruppen"
|
msgstr "Gruppen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Beschreibung"
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -647,36 +656,36 @@ msgstr "Beschreibung"
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr "Status"
|
msgstr "Status"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "Mitgliederzahl"
|
msgstr "Mitgliederzahl"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "Verborgen"
|
msgstr "Verborgen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "Öffnen"
|
msgstr "Öffnen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "Anfragbar"
|
msgstr "Anfragbar"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr "Mitglieder ansehen"
|
msgstr "Mitglieder ansehen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr "Mitglieder Protokoll"
|
msgstr "Mitglieder Protokoll"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr "Direktlink kopieren"
|
msgstr "Direktlink kopieren"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr "Keine Gruppen vorhanden."
|
msgstr "Keine Gruppen vorhanden."
|
||||||
|
|
||||||
@@ -685,19 +694,19 @@ msgstr "Keine Gruppen vorhanden."
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "Verfügbare Gruppen"
|
msgstr "Verfügbare Gruppen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "Verlassen"
|
msgstr "Verlassen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "Beitreten"
|
msgstr "Beitreten"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "Anfrage"
|
msgstr "Anfrage"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "Keine Gruppen verfügbar"
|
msgstr "Keine Gruppen verfügbar"
|
||||||
|
|
||||||
@@ -709,24 +718,24 @@ msgstr "Gruppenverwaltung"
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr "Beitrittsgesuche"
|
msgstr "Beitrittsgesuche"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr "Austrittsgesuche"
|
msgstr "Austrittsgesuche"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "Gruppen"
|
msgstr "Gruppen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "Akzeptieren"
|
msgstr "Akzeptieren"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "Ablehnen"
|
msgstr "Ablehnen"
|
||||||
@@ -735,19 +744,19 @@ msgstr "Ablehnen"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "Keine Gruppenbeitrittsanfragen."
|
msgstr "Keine Gruppenbeitrittsanfragen."
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "Keine Gruppenaustrittsanfragen"
|
msgstr "Keine Gruppenaustrittsanfragen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr "Toggle Navigation"
|
msgstr "Toggle Navigation"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr "Gruppenanfragen"
|
msgstr "Gruppenanfragen"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr "Gruppenmitgliedschaft"
|
msgstr "Gruppenmitgliedschaft"
|
||||||
|
|
||||||
@@ -1264,7 +1273,7 @@ msgstr "Flotten Comms:"
|
|||||||
|
|
||||||
#: allianceauth/services/forms.py:9
|
#: allianceauth/services/forms.py:9
|
||||||
msgid "Fleet Type:"
|
msgid "Fleet Type:"
|
||||||
msgstr "Flottenzeit:"
|
msgstr "Flottenart:"
|
||||||
|
|
||||||
#: allianceauth/services/forms.py:10
|
#: allianceauth/services/forms.py:10
|
||||||
msgid "Ship Priorities:"
|
msgid "Ship Priorities:"
|
||||||
@@ -1316,7 +1325,7 @@ msgstr "Discord Konto deaktiviert"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Dein Discord Konto wurde automatisch durch Auth deaktiviert. Wenn Du glaubst"
|
"Dein Discord Konto wurde automatisch durch Auth deaktiviert. Wenn Du glaubst"
|
||||||
@@ -2089,3 +2098,6 @@ msgstr "Neuen Timer hinzugefügt in %(system)s um %(time)s."
|
|||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr "Änderungen am Timer gespeichert"
|
msgstr "Änderungen am Timer gespeichert"
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr "Portrait"
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -4,17 +4,17 @@
|
|||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# frank1210 <francolopez_16@hotmail.com>, 2020
|
|
||||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||||
|
# frank1210 <francolopez_16@hotmail.com>, 2020
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
|
"Last-Translator: frank1210 <francolopez_16@hotmail.com>, 2020\n"
|
||||||
"Language-Team: Spanish (https://www.transifex.com/alliance-auth/teams/107430/es/)\n"
|
"Language-Team: Spanish (https://www.transifex.com/alliance-auth/teams/107430/es/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -79,7 +79,7 @@ msgstr "Personajes"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -161,26 +161,26 @@ msgstr ""
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "Imposible validar con el personaje seleccionado."
|
msgstr "Imposible validar con el personaje seleccionado."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "El token de registracion expiro."
|
msgstr "El token de registracion expiro."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Confirmacion de mail enviada. Por favor siga el enlace para confirmar "
|
"Confirmacion de mail enviada. Por favor siga el enlace para confirmar "
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Se ha confirmado su direccion de mail. Por favor igrese su token para "
|
"Se ha confirmado su direccion de mail. Por favor igrese su token para "
|
||||||
"continuar."
|
"continuar."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "Registracion de nuevas cuentas no es permitido por el momento."
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
msgid "Corporation Stats"
|
msgid "Corporation Stats"
|
||||||
@@ -227,16 +227,16 @@ msgstr "Ultima Actualizacion:"
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "Personaje"
|
msgstr "Personaje"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -546,36 +546,35 @@ msgstr "Participacion de flota registrada."
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "Enlace de participacion expirado."
|
msgstr "Enlace de participacion expirado."
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr "Manejo de Grupo"
|
msgstr "Manejo de Grupo"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr "Log de Auditoria"
|
msgstr "Log de Auditoria"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Volver"
|
msgstr "Volver"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "Fecha/Hora"
|
msgstr "Fecha/Hora"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr "Solicitante"
|
msgstr "Solicitante"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Tipo"
|
msgstr "Tipo"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -586,11 +585,19 @@ msgstr "Tipo"
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr "Accion"
|
msgstr "Accion"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr "Actor"
|
msgstr "Actor"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "No se encontraron entradas para este grupo."
|
msgstr "No se encontraron entradas para este grupo."
|
||||||
|
|
||||||
@@ -598,22 +605,24 @@ msgstr "No se encontraron entradas para este grupo."
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr "Miembros del Grupo"
|
msgstr "Miembros del Grupo"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr "Retrato"
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "Remover del grupo"
|
msgstr "Remover del grupo"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "no hay miembros para listar."
|
msgstr "no hay miembros para listar."
|
||||||
|
|
||||||
@@ -621,18 +630,18 @@ msgstr "no hay miembros para listar."
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr "Membresia de grupos"
|
msgstr "Membresia de grupos"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Grupos"
|
msgstr "Grupos"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripcion"
|
msgstr "Descripcion"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -641,36 +650,36 @@ msgstr "Descripcion"
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr "Estado"
|
msgstr "Estado"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "Contador de miembros"
|
msgstr "Contador de miembros"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "Escondido"
|
msgstr "Escondido"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "Abierto"
|
msgstr "Abierto"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "Solicitable"
|
msgstr "Solicitable"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr "Ver Miembros"
|
msgstr "Ver Miembros"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr "Auditar Miembros"
|
msgstr "Auditar Miembros"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr "No hay grupos para listar"
|
msgstr "No hay grupos para listar"
|
||||||
|
|
||||||
@@ -679,19 +688,19 @@ msgstr "No hay grupos para listar"
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "Grupos Disponibles"
|
msgstr "Grupos Disponibles"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "Dejar"
|
msgstr "Dejar"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "Unirse"
|
msgstr "Unirse"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "Solicitar"
|
msgstr "Solicitar"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "No hay grupos disponibles"
|
msgstr "No hay grupos disponibles"
|
||||||
|
|
||||||
@@ -703,24 +712,24 @@ msgstr "Manejo de Grupos"
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "Grupo"
|
msgstr "Grupo"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "Aceptar"
|
msgstr "Aceptar"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "Rechazar"
|
msgstr "Rechazar"
|
||||||
@@ -729,19 +738,19 @@ msgstr "Rechazar"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "No hay solicitudes de ingreso."
|
msgstr "No hay solicitudes de ingreso."
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "No hay solicitudes paradejar el grupo."
|
msgstr "No hay solicitudes paradejar el grupo."
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr "Navegacion"
|
msgstr "Navegacion"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr "Solicitudes de Grupo"
|
msgstr "Solicitudes de Grupo"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr "Membresia de Grupo"
|
msgstr "Membresia de Grupo"
|
||||||
|
|
||||||
@@ -1309,7 +1318,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2065,3 +2074,6 @@ msgstr "Se agrego un nuevo timer en %(system)s a las %(time)s."
|
|||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr "Se guardaron los cambios en el timer."
|
msgstr "Se guardaron los cambios en el timer."
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr "Retrato"
|
||||||
|
|||||||
Binary file not shown.
@@ -6,15 +6,16 @@
|
|||||||
# Translators:
|
# Translators:
|
||||||
# François LACROIX-DURANT <umbre@fallenstarscreations.com>, 2020
|
# François LACROIX-DURANT <umbre@fallenstarscreations.com>, 2020
|
||||||
# Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2020
|
# Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2020
|
||||||
|
# Keven D. <theenarki@gmail.com>, 2020
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2020\n"
|
"Last-Translator: Keven D. <theenarki@gmail.com>, 2020\n"
|
||||||
"Language-Team: French (France) (https://www.transifex.com/alliance-auth/teams/107430/fr_FR/)\n"
|
"Language-Team: French (France) (https://www.transifex.com/alliance-auth/teams/107430/fr_FR/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -82,7 +83,7 @@ msgstr "Personnages"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -167,11 +168,11 @@ msgstr "Impossible d'ajouter %(name)s à votre compte: ils ont déjà un compte.
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "Personnage principal : échec de l'identification."
|
msgstr "Personnage principal : échec de l'identification."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "Le token d'enregistrement est expiré."
|
msgstr "Le token d'enregistrement est expiré."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
@@ -179,14 +180,14 @@ msgstr ""
|
|||||||
"Email de confirmation envoyé. Cliquez sur le lien pour valider votre adresse"
|
"Email de confirmation envoyé. Cliquez sur le lien pour valider votre adresse"
|
||||||
" email."
|
" email."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Votre adresse email a été confirmé. Veuillez vous connecter pour continuer."
|
"Votre adresse email a été confirmé. Veuillez vous connecter pour continuer."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "Création de nouveaux comptes interdit à ce moment."
|
msgstr "La création de nouveaux comptes n'est pas actuellement permise."
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
msgid "Corporation Stats"
|
msgid "Corporation Stats"
|
||||||
@@ -233,16 +234,16 @@ msgstr "Dernière mise à jour:"
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "Personnage"
|
msgstr "Personnage"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -552,36 +553,35 @@ msgstr "Participation à la flotte enregistrée."
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "le lien a expiré"
|
msgstr "le lien a expiré"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr "Gestion de groupe"
|
msgstr "Gestion de groupe"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Retour"
|
msgstr "Retour"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "Date/Heure"
|
msgstr "Date/Heure"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr "Demandeur"
|
msgstr "Demandeur"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Type"
|
msgstr "Type"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -592,11 +592,19 @@ msgstr "Type"
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr "Action"
|
msgstr "Action"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr "Acteur"
|
msgstr "Acteur"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "Aucune entrée trouvée pour ce groupe."
|
msgstr "Aucune entrée trouvée pour ce groupe."
|
||||||
|
|
||||||
@@ -604,22 +612,24 @@ msgstr "Aucune entrée trouvée pour ce groupe."
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr "Membres du groupe"
|
msgstr "Membres du groupe"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr "Portrait"
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "Organisation"
|
msgstr "Organisation"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "Retirer du groupe"
|
msgstr "Retirer du groupe"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "Aucun membre à afficher"
|
msgstr "Aucun membre à afficher"
|
||||||
|
|
||||||
@@ -627,18 +637,18 @@ msgstr "Aucun membre à afficher"
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr "Groupe appartenance "
|
msgstr "Groupe appartenance "
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Groupes"
|
msgstr "Groupes"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Description"
|
msgstr "Description"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -647,36 +657,36 @@ msgstr "Description"
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr "Statut"
|
msgstr "Statut"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "Nombre de membre"
|
msgstr "Nombre de membre"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "Caché"
|
msgstr "Caché"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "Ouvert"
|
msgstr "Ouvert"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "Demandable"
|
msgstr "Demandable"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr "Voir les membres"
|
msgstr "Voir les membres"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr "Copier le lien d'invitation directe"
|
msgstr "Copier le lien d'invitation directe"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr "Aucun groupe à afficher"
|
msgstr "Aucun groupe à afficher"
|
||||||
|
|
||||||
@@ -685,19 +695,19 @@ msgstr "Aucun groupe à afficher"
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "Groupes disponibles"
|
msgstr "Groupes disponibles"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "Quitter"
|
msgstr "Quitter"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "Rejoindre"
|
msgstr "Rejoindre"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "Demander"
|
msgstr "Demander"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "Aucun groupe disponible"
|
msgstr "Aucun groupe disponible"
|
||||||
|
|
||||||
@@ -709,24 +719,24 @@ msgstr "Gestion de groupe"
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr "Demandes de recrutement"
|
msgstr "Demandes de recrutement"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr "Demande de départ"
|
msgstr "Demande de départ"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "Groupe"
|
msgstr "Groupe"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "Accepter"
|
msgstr "Accepter"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "Rejeter"
|
msgstr "Rejeter"
|
||||||
@@ -735,19 +745,19 @@ msgstr "Rejeter"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "Aucune demande en cours"
|
msgstr "Aucune demande en cours"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "Aucune demande en cours"
|
msgstr "Aucune demande en cours"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr "Activer navigation"
|
msgstr "Activer navigation"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr "Demandes de groupe"
|
msgstr "Demandes de groupe"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr "Groupe appartenance "
|
msgstr "Groupe appartenance "
|
||||||
|
|
||||||
@@ -1055,11 +1065,11 @@ msgstr "Titre"
|
|||||||
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:57
|
#: allianceauth/notifications/templates/notifications/list.html:57
|
||||||
msgid "No unread notifications."
|
msgid "No unread notifications."
|
||||||
msgstr ""
|
msgstr "Aucune notification non lue."
|
||||||
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:89
|
#: allianceauth/notifications/templates/notifications/list.html:89
|
||||||
msgid "No read notifications."
|
msgid "No read notifications."
|
||||||
msgstr ""
|
msgstr "Aucune notification lue."
|
||||||
|
|
||||||
#: allianceauth/notifications/templates/notifications/view.html:5
|
#: allianceauth/notifications/templates/notifications/view.html:5
|
||||||
#: allianceauth/notifications/templates/notifications/view.html:11
|
#: allianceauth/notifications/templates/notifications/view.html:11
|
||||||
@@ -1072,7 +1082,7 @@ msgstr "Vous n'êtes pas autorisé a voir cette alerte."
|
|||||||
|
|
||||||
#: allianceauth/notifications/views.py:48
|
#: allianceauth/notifications/views.py:48
|
||||||
msgid "Deleted notification."
|
msgid "Deleted notification."
|
||||||
msgstr "Supprimer l'alerte."
|
msgstr "Alerte supprimée."
|
||||||
|
|
||||||
#: allianceauth/notifications/views.py:52
|
#: allianceauth/notifications/views.py:52
|
||||||
msgid "Failed to locate notification."
|
msgid "Failed to locate notification."
|
||||||
@@ -1088,7 +1098,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: allianceauth/optimer/auth_hooks.py:9
|
#: allianceauth/optimer/auth_hooks.py:9
|
||||||
msgid "Fleet Operations"
|
msgid "Fleet Operations"
|
||||||
msgstr ""
|
msgstr "Opérations de flotte"
|
||||||
|
|
||||||
#: allianceauth/optimer/form.py:6
|
#: allianceauth/optimer/form.py:6
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:10
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:10
|
||||||
@@ -1108,7 +1118,7 @@ msgstr "Nom de l'opération"
|
|||||||
#: allianceauth/optimer/form.py:11
|
#: allianceauth/optimer/form.py:11
|
||||||
#: allianceauth/srp/templates/srp/management.html:40
|
#: allianceauth/srp/templates/srp/management.html:40
|
||||||
msgid "Fleet Commander"
|
msgid "Fleet Commander"
|
||||||
msgstr ""
|
msgstr "Commandant de flotte"
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/add.html:7
|
#: allianceauth/optimer/templates/optimer/add.html:7
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:14
|
#: allianceauth/optimer/templates/optimer/management.html:14
|
||||||
@@ -1132,11 +1142,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:6
|
#: allianceauth/optimer/templates/optimer/management.html:6
|
||||||
msgid "Fleet Operation Management"
|
msgid "Fleet Operation Management"
|
||||||
msgstr ""
|
msgstr "Gestion des opérations de flotte"
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:11
|
#: allianceauth/optimer/templates/optimer/management.html:11
|
||||||
msgid "Fleet Operation Timers"
|
msgid "Fleet Operation Timers"
|
||||||
msgstr ""
|
msgstr "Minuteurs d'opération de flotte"
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:21
|
#: allianceauth/optimer/templates/optimer/management.html:21
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:23
|
#: allianceauth/timerboard/templates/timerboard/view.html:23
|
||||||
@@ -1146,22 +1156,22 @@ msgstr "Heure d'Eve actuelle:"
|
|||||||
#: allianceauth/optimer/templates/optimer/management.html:27
|
#: allianceauth/optimer/templates/optimer/management.html:27
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:189
|
#: allianceauth/timerboard/templates/timerboard/view.html:189
|
||||||
msgid "Next Timers"
|
msgid "Next Timers"
|
||||||
msgstr ""
|
msgstr "Prochains minuteurs"
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:31
|
#: allianceauth/optimer/templates/optimer/management.html:31
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:353
|
#: allianceauth/timerboard/templates/timerboard/view.html:353
|
||||||
msgid "No upcoming timers."
|
msgid "No upcoming timers."
|
||||||
msgstr ""
|
msgstr "Aucun minuteur à venir."
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:34
|
#: allianceauth/optimer/templates/optimer/management.html:34
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:357
|
#: allianceauth/timerboard/templates/timerboard/view.html:357
|
||||||
msgid "Past Timers"
|
msgid "Past Timers"
|
||||||
msgstr ""
|
msgstr "Minuteurs précédents"
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:38
|
#: allianceauth/optimer/templates/optimer/management.html:38
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:521
|
#: allianceauth/timerboard/templates/timerboard/view.html:521
|
||||||
msgid "No past timers."
|
msgid "No past timers."
|
||||||
msgstr ""
|
msgstr "Aucun minuteur précédent."
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/update.html:7
|
#: allianceauth/optimer/templates/optimer/update.html:7
|
||||||
#: allianceauth/optimer/templates/optimer/update.html:16
|
#: allianceauth/optimer/templates/optimer/update.html:16
|
||||||
@@ -1176,17 +1186,17 @@ msgstr "L'objectif de la flotte n'existe pas."
|
|||||||
#: allianceauth/optimer/views.py:55
|
#: allianceauth/optimer/views.py:55
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Created operation timer for %(opname)s."
|
msgid "Created operation timer for %(opname)s."
|
||||||
msgstr ""
|
msgstr "Minuteur d'opération créé pour %(opname)s."
|
||||||
|
|
||||||
#: allianceauth/optimer/views.py:73
|
#: allianceauth/optimer/views.py:73
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Removed operation timer for %(opname)s."
|
msgid "Removed operation timer for %(opname)s."
|
||||||
msgstr ""
|
msgstr "Minuteur d'opération supprimé pour %(opname)s."
|
||||||
|
|
||||||
#: allianceauth/optimer/views.py:96
|
#: allianceauth/optimer/views.py:96
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Saved changes to operation timer for %(opname)s."
|
msgid "Saved changes to operation timer for %(opname)s."
|
||||||
msgstr ""
|
msgstr "Minuteur d'opération modifié pour %(opname)s."
|
||||||
|
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:6
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:6
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:10
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:10
|
||||||
@@ -1256,7 +1266,7 @@ msgstr "Nom de la Flotte:"
|
|||||||
|
|
||||||
#: allianceauth/services/forms.py:7
|
#: allianceauth/services/forms.py:7
|
||||||
msgid "Fleet Commander:"
|
msgid "Fleet Commander:"
|
||||||
msgstr "Comandant de la flotte:"
|
msgstr "Commandant de la flotte:"
|
||||||
|
|
||||||
#: allianceauth/services/forms.py:8
|
#: allianceauth/services/forms.py:8
|
||||||
msgid "Fleet Comms:"
|
msgid "Fleet Comms:"
|
||||||
@@ -1316,7 +1326,7 @@ msgstr "Compte Discord Désactivé"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Votre compte Discord a été désactivé automatiquement par Auth. Si vous "
|
"Votre compte Discord a été désactivé automatiquement par Auth. Si vous "
|
||||||
@@ -1395,11 +1405,11 @@ msgstr "Une erreur est survenue durant l'activation de votre compte IPSuite4."
|
|||||||
|
|
||||||
#: allianceauth/services/modules/ips4/views.py:53
|
#: allianceauth/services/modules/ips4/views.py:53
|
||||||
msgid "Reset IPSuite4 password."
|
msgid "Reset IPSuite4 password."
|
||||||
msgstr "Supprimer le mot de passe IPSuite4."
|
msgstr "Réinitialiser le mot de passe IPSuite4."
|
||||||
|
|
||||||
#: allianceauth/services/modules/ips4/views.py:80
|
#: allianceauth/services/modules/ips4/views.py:80
|
||||||
msgid "Set IPSuite4 password."
|
msgid "Set IPSuite4 password."
|
||||||
msgstr "Mettre un mot de passe IPSuite4."
|
msgstr "Définir le mot de passe IPSuite4."
|
||||||
|
|
||||||
#: allianceauth/services/modules/ips4/views.py:100
|
#: allianceauth/services/modules/ips4/views.py:100
|
||||||
msgid "Deactivated IPSuite4 account."
|
msgid "Deactivated IPSuite4 account."
|
||||||
@@ -1444,7 +1454,7 @@ msgstr "Une erreur est survenue durant la gestion de votre compte Jabber."
|
|||||||
|
|
||||||
#: allianceauth/services/modules/openfire/views.py:70
|
#: allianceauth/services/modules/openfire/views.py:70
|
||||||
msgid "Reset jabber password."
|
msgid "Reset jabber password."
|
||||||
msgstr "Supprimer le mot de passe Jabber."
|
msgstr "Réinitialiser le mot de passe Jabber."
|
||||||
|
|
||||||
#: allianceauth/services/modules/openfire/views.py:119
|
#: allianceauth/services/modules/openfire/views.py:119
|
||||||
#, python-format
|
#, python-format
|
||||||
@@ -1453,7 +1463,7 @@ msgstr "Broadcast jabber envoyé à %s"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/openfire/views.py:148
|
#: allianceauth/services/modules/openfire/views.py:148
|
||||||
msgid "Set jabber password."
|
msgid "Set jabber password."
|
||||||
msgstr "Mettre un mot de passe Jabber."
|
msgstr "Définir le mot de passe Jabber."
|
||||||
|
|
||||||
#: allianceauth/services/modules/phpbb3/views.py:34
|
#: allianceauth/services/modules/phpbb3/views.py:34
|
||||||
msgid "Activated forum account."
|
msgid "Activated forum account."
|
||||||
@@ -1472,11 +1482,11 @@ msgstr "Compte de forum désactivé."
|
|||||||
|
|
||||||
#: allianceauth/services/modules/phpbb3/views.py:71
|
#: allianceauth/services/modules/phpbb3/views.py:71
|
||||||
msgid "Reset forum password."
|
msgid "Reset forum password."
|
||||||
msgstr "Réinitialisé le mot de passe du forum"
|
msgstr "Réinitialiser le mot de passe du forum."
|
||||||
|
|
||||||
#: allianceauth/services/modules/phpbb3/views.py:100
|
#: allianceauth/services/modules/phpbb3/views.py:100
|
||||||
msgid "Set forum password."
|
msgid "Set forum password."
|
||||||
msgstr "Définir mot de passe du forum."
|
msgstr "Définir le mot de passe du forum."
|
||||||
|
|
||||||
#: allianceauth/services/modules/smf/views.py:34
|
#: allianceauth/services/modules/smf/views.py:34
|
||||||
msgid "Activated SMF account."
|
msgid "Activated SMF account."
|
||||||
@@ -1495,11 +1505,11 @@ msgstr "Compte SMF désactivé"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/smf/views.py:72
|
#: allianceauth/services/modules/smf/views.py:72
|
||||||
msgid "Reset SMF password."
|
msgid "Reset SMF password."
|
||||||
msgstr "Réinitialisé le mot de passe SMF"
|
msgstr "Réinitialiser le mot de passe SMF."
|
||||||
|
|
||||||
#: allianceauth/services/modules/smf/views.py:100
|
#: allianceauth/services/modules/smf/views.py:100
|
||||||
msgid "Set SMF password."
|
msgid "Set SMF password."
|
||||||
msgstr "Définir mot de passe SMF."
|
msgstr "Définir le mot de passe SMF."
|
||||||
|
|
||||||
#: allianceauth/services/modules/teamspeak3/forms.py:14
|
#: allianceauth/services/modules/teamspeak3/forms.py:14
|
||||||
#, python-format
|
#, python-format
|
||||||
@@ -1559,11 +1569,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: allianceauth/services/modules/xenforo/views.py:65
|
#: allianceauth/services/modules/xenforo/views.py:65
|
||||||
msgid "Reset XenForo account password."
|
msgid "Reset XenForo account password."
|
||||||
msgstr ""
|
msgstr "Réinitialiser le mot de passe du compte XenForo."
|
||||||
|
|
||||||
#: allianceauth/services/modules/xenforo/views.py:91
|
#: allianceauth/services/modules/xenforo/views.py:91
|
||||||
msgid "Changed XenForo password."
|
msgid "Changed XenForo password."
|
||||||
msgstr ""
|
msgstr "Mot de passe XenForo modifié."
|
||||||
|
|
||||||
#: allianceauth/services/templates/services/fleetformattertool.html:6
|
#: allianceauth/services/templates/services/fleetformattertool.html:6
|
||||||
msgid "Fleet Formatter Tool"
|
msgid "Fleet Formatter Tool"
|
||||||
@@ -1600,16 +1610,16 @@ msgstr ""
|
|||||||
#: allianceauth/services/templates/services/service_password.html:6
|
#: allianceauth/services/templates/services/service_password.html:6
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(service_name)s Password Change"
|
msgid "%(service_name)s Password Change"
|
||||||
msgstr ""
|
msgstr "Modification du mot de passe %(service_name)s"
|
||||||
|
|
||||||
#: allianceauth/services/templates/services/service_password.html:10
|
#: allianceauth/services/templates/services/service_password.html:10
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Set %(service_name)s Password"
|
msgid "Set %(service_name)s Password"
|
||||||
msgstr ""
|
msgstr "Définir le mot de passe %(service_name)s"
|
||||||
|
|
||||||
#: allianceauth/services/templates/services/service_password.html:19
|
#: allianceauth/services/templates/services/service_password.html:19
|
||||||
msgid "Set Password"
|
msgid "Set Password"
|
||||||
msgstr ""
|
msgstr "Définir le mot de passe"
|
||||||
|
|
||||||
#: allianceauth/services/templates/services/services.html:5
|
#: allianceauth/services/templates/services/services.html:5
|
||||||
msgid "Services Management"
|
msgid "Services Management"
|
||||||
@@ -2032,12 +2042,12 @@ msgstr "Limité à la Corporation"
|
|||||||
|
|
||||||
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:11
|
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:11
|
||||||
msgid "Delete Timer"
|
msgid "Delete Timer"
|
||||||
msgstr "Supprimer minuteur"
|
msgstr "Supprimer le minuteur"
|
||||||
|
|
||||||
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:19
|
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:19
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Are you sure you want to delete timer \"%(object)s\"?"
|
msgid "Are you sure you want to delete timer \"%(object)s\"?"
|
||||||
msgstr "Etes vous sur de vouloir supprimer le minuteur \"%(object)s\" ?"
|
msgstr "Êtes-vous sûr de vouloir supprimer le minuteur \"%(object)s\" ?"
|
||||||
|
|
||||||
#: allianceauth/timerboard/templates/timerboard/timer_create_form.html:5
|
#: allianceauth/timerboard/templates/timerboard/timer_create_form.html:5
|
||||||
#: allianceauth/timerboard/templates/timerboard/timer_create_form.html:13
|
#: allianceauth/timerboard/templates/timerboard/timer_create_form.html:13
|
||||||
@@ -2076,8 +2086,11 @@ msgstr "Structure"
|
|||||||
#: allianceauth/timerboard/views.py:74
|
#: allianceauth/timerboard/views.py:74
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Added new timer in %(system)s at %(time)s."
|
msgid "Added new timer in %(system)s at %(time)s."
|
||||||
msgstr "Ajout d'un nouveau timer dans%(system)s à %(time)s"
|
msgstr "Nouveau minuteur ajouté dans %(system)s à %(time)s"
|
||||||
|
|
||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr "Changements du Minuteur sauvegardés."
|
msgstr "Changements du minuteur sauvegardés."
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr "Portrait"
|
||||||
|
|||||||
Binary file not shown.
@@ -5,15 +5,16 @@
|
|||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# Foch Petain <brigadier.rockforward@gmail.com>, 2020
|
# Foch Petain <brigadier.rockforward@gmail.com>, 2020
|
||||||
|
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Foch Petain <brigadier.rockforward@gmail.com>, 2020\n"
|
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
|
||||||
"Language-Team: Japanese (https://www.transifex.com/alliance-auth/teams/107430/ja/)\n"
|
"Language-Team: Japanese (https://www.transifex.com/alliance-auth/teams/107430/ja/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -79,7 +80,7 @@ msgstr "キャラクター"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -159,22 +160,22 @@ msgstr "%(name)sをアカウントに追加することができません。す
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "選択されたキャラクターの認証が行えませんでした。"
|
msgstr "選択されたキャラクターの認証が行えませんでした。"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "Registration tokenが期限切れです。"
|
msgstr "Registration tokenが期限切れです。"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
msgstr "確認のメールを送りました。メール内のリンクをご確認の上、メールアドレスの認証を完了させてください。"
|
msgstr "確認のメールを送りました。メール内のリンクをご確認の上、メールアドレスの認証を完了させてください。"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr "メールアドレスの確認が取れました。Loginしてください。"
|
msgstr "メールアドレスの確認が取れました。Loginしてください。"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "現在新規アカウントの登録を停止しております。"
|
msgstr "現在新規アカウントの登録を停止しております。"
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
@@ -222,16 +223,16 @@ msgstr "最終活動日:"
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "Character"
|
msgstr "Character"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -538,36 +539,35 @@ msgstr "Fleet参加が登録されました。"
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "Fat-Linkの有効期間が終了してます。"
|
msgstr "Fat-Linkの有効期間が終了してます。"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "戻る"
|
msgstr "戻る"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "日付/時間"
|
msgstr "日付/時間"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -578,11 +578,19 @@ msgstr ""
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "この Group での entry が見つかりませんでした。"
|
msgstr "この Group での entry が見つかりませんでした。"
|
||||||
|
|
||||||
@@ -590,22 +598,24 @@ msgstr "この Group での entry が見つかりませんでした。"
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "Group から削除"
|
msgstr "Group から削除"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "Groupメンバーはリストにいません。"
|
msgstr "Groupメンバーはリストにいません。"
|
||||||
|
|
||||||
@@ -613,18 +623,18 @@ msgstr "Groupメンバーはリストにいません。"
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -633,36 +643,36 @@ msgstr ""
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "Member Count"
|
msgstr "Member Count"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "閉じる"
|
msgstr "閉じる"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "開く"
|
msgstr "開く"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "申請可能"
|
msgstr "申請可能"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -671,19 +681,19 @@ msgstr ""
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "参加可能Group"
|
msgstr "参加可能Group"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "脱退"
|
msgstr "脱退"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "参加"
|
msgstr "参加"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "申請"
|
msgstr "申請"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "参加可能なGroupがありません。"
|
msgstr "参加可能なGroupがありません。"
|
||||||
|
|
||||||
@@ -695,24 +705,24 @@ msgstr ""
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr "参加希望を出す"
|
msgstr "参加希望を出す"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr "脱退希望を出す"
|
msgstr "脱退希望を出す"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "承認"
|
msgstr "承認"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "拒否"
|
msgstr "拒否"
|
||||||
@@ -721,19 +731,19 @@ msgstr "拒否"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "グループ参加希望はありません。"
|
msgstr "グループ参加希望はありません。"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "グループ脱退希望はありません。"
|
msgstr "グループ脱退希望はありません。"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1298,9 +1308,9 @@ msgstr "Discordのアカウントを無効化"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr "あなたのDiscordアカウントは管理者によって無効化されました。もし、これが間違いの場合、管理者に確認してください。"
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
|
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
|
||||||
msgid "Join the Discord server"
|
msgid "Join the Discord server"
|
||||||
@@ -2055,3 +2065,6 @@ msgstr ""
|
|||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr ""
|
||||||
|
|||||||
Binary file not shown.
@@ -5,18 +5,19 @@
|
|||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# None None <khd1226543@gmail.com>, 2020
|
# None None <khd1226543@gmail.com>, 2020
|
||||||
# Olgeda Choi <undead.choi@gmail.com>, 2020
|
|
||||||
# Seowon Jung <seowon@hawaii.edu>, 2020
|
# Seowon Jung <seowon@hawaii.edu>, 2020
|
||||||
|
# Olgeda Choi <undead.choi@gmail.com>, 2020
|
||||||
# Lahty <js03js70@gmail.com>, 2020
|
# Lahty <js03js70@gmail.com>, 2020
|
||||||
|
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Lahty <js03js70@gmail.com>, 2020\n"
|
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
|
||||||
"Language-Team: Korean (Korea) (https://www.transifex.com/alliance-auth/teams/107430/ko_KR/)\n"
|
"Language-Team: Korean (Korea) (https://www.transifex.com/alliance-auth/teams/107430/ko_KR/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -83,7 +84,7 @@ msgstr "캐릭터"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -163,22 +164,22 @@ msgstr "계정에 %(name)s를 추가하지 못했습니다. 이미 추가된 계
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "선택한 캐릭터로 인증을 수행할 수 없음"
|
msgstr "선택한 캐릭터로 인증을 수행할 수 없음"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "등록토큰 만료"
|
msgstr "등록토큰 만료"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
msgstr "확인 메일 전송됨. 다음 링크를 눌러 이메일 주소를 확인하세요."
|
msgstr "확인 메일 전송됨. 다음 링크를 눌러 이메일 주소를 확인하세요."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr "이메일 주소가 확인되었습니다. 로그인 해주세요."
|
msgstr "이메일 주소가 확인되었습니다. 로그인 해주세요."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "현재 새로운 계정 등록은 받지않습니다."
|
msgstr "현재 새로운 계정 등록은 받지않습니다."
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
@@ -226,16 +227,16 @@ msgstr "마지막 업데이트"
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "캐릭터"
|
msgstr "캐릭터"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -542,36 +543,35 @@ msgstr "플릿 참여 등록됨"
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "플릿활동추적 링크 기한만료"
|
msgstr "플릿활동추적 링크 기한만료"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr "그룹 관리"
|
msgstr "그룹 관리"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr "감사 기록"
|
msgstr "감사 기록"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "돌아가기"
|
msgstr "돌아가기"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "날짜/시간"
|
msgstr "날짜/시간"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr "요청인"
|
msgstr "요청인"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "타입"
|
msgstr "타입"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -582,11 +582,19 @@ msgstr "타입"
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr "활동"
|
msgstr "활동"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr "활동한 사람"
|
msgstr "활동한 사람"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "이 그룹에는 항목 없음"
|
msgstr "이 그룹에는 항목 없음"
|
||||||
|
|
||||||
@@ -594,22 +602,24 @@ msgstr "이 그룹에는 항목 없음"
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr "그룹 멤버"
|
msgstr "그룹 멤버"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr "포트레잇"
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "조직"
|
msgstr "조직"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "그룹에서 제거"
|
msgstr "그룹에서 제거"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "목록에 그룹 멤버 없음"
|
msgstr "목록에 그룹 멤버 없음"
|
||||||
|
|
||||||
@@ -617,18 +627,18 @@ msgstr "목록에 그룹 멤버 없음"
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr "그룹 멤버쉽"
|
msgstr "그룹 멤버쉽"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "그룹"
|
msgstr "그룹"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "설명"
|
msgstr "설명"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -637,36 +647,36 @@ msgstr "설명"
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr "상태"
|
msgstr "상태"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "멤버 수"
|
msgstr "멤버 수"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "숨김"
|
msgstr "숨김"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "열기"
|
msgstr "열기"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "요청 가능"
|
msgstr "요청 가능"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr "멤버 보기"
|
msgstr "멤버 보기"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr "멤버 검사"
|
msgstr "멤버 검사"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr "직접 참여 링크 복사"
|
msgstr "직접 참여 링크 복사"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr "목록에 그룹 없음"
|
msgstr "목록에 그룹 없음"
|
||||||
|
|
||||||
@@ -675,19 +685,19 @@ msgstr "목록에 그룹 없음"
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "사용 가능한 그룹"
|
msgstr "사용 가능한 그룹"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "떠나기"
|
msgstr "떠나기"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "참여하기"
|
msgstr "참여하기"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "요청하기"
|
msgstr "요청하기"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "사용 가능한 그룹 없음."
|
msgstr "사용 가능한 그룹 없음."
|
||||||
|
|
||||||
@@ -699,24 +709,24 @@ msgstr "그룹 관리"
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr "가입 요청"
|
msgstr "가입 요청"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr "탈퇴 요청"
|
msgstr "탈퇴 요청"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "그룹"
|
msgstr "그룹"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "수락"
|
msgstr "수락"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "거절"
|
msgstr "거절"
|
||||||
@@ -725,19 +735,19 @@ msgstr "거절"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "가입 요청 없음"
|
msgstr "가입 요청 없음"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "탈퇴 요청 없음"
|
msgstr "탈퇴 요청 없음"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr "네비게이션 전환"
|
msgstr "네비게이션 전환"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr "그룹 요청"
|
msgstr "그룹 요청"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr "그룹 멤버쉽"
|
msgstr "그룹 멤버쉽"
|
||||||
|
|
||||||
@@ -1302,7 +1312,7 @@ msgstr "디스코드 계정 비활성화"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr "Auth에 의해 자동으로 디스코드 계정이 비활성화됐습니다. 원치 않는 사항일 경우, 관리자에게 문의해 주세요."
|
msgstr "Auth에 의해 자동으로 디스코드 계정이 비활성화됐습니다. 원치 않는 사항일 경우, 관리자에게 문의해 주세요."
|
||||||
|
|
||||||
@@ -2057,3 +2067,6 @@ msgstr "%(time)s 에 있을 %(system)s 타이머를 추가했습니다."
|
|||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr "타이머 변경사항이 저장되었습니다."
|
msgstr "타이머 변경사항이 저장되었습니다."
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr "포트레잇"
|
||||||
|
|||||||
Binary file not shown.
@@ -5,15 +5,17 @@
|
|||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# Alexander Gess <de.alex.gess@gmail.com>, 2020
|
# Alexander Gess <de.alex.gess@gmail.com>, 2020
|
||||||
|
# Yuriy K <thedjcooltv@gmail.com>, 2020
|
||||||
|
# Андрей Зубков <and.vareba81@gmail.com>, 2020
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Alexander Gess <de.alex.gess@gmail.com>, 2020\n"
|
"Last-Translator: Андрей Зубков <and.vareba81@gmail.com>, 2020\n"
|
||||||
"Language-Team: Russian (https://www.transifex.com/alliance-auth/teams/107430/ru/)\n"
|
"Language-Team: Russian (https://www.transifex.com/alliance-auth/teams/107430/ru/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -70,7 +72,7 @@ msgstr "Сменить основного персонажа"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:101
|
#: allianceauth/authentication/templates/authentication/dashboard.html:101
|
||||||
msgid "Group Memberships"
|
msgid "Group Memberships"
|
||||||
msgstr "Групповое участие"
|
msgstr "Роли"
|
||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:121
|
#: allianceauth/authentication/templates/authentication/dashboard.html:121
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
|
||||||
@@ -80,7 +82,7 @@ msgstr "Персонажи"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -163,23 +165,23 @@ msgstr "Персонаж %(name)s уже добавлен."
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "Невозможно авторизировать этого персонажа. "
|
msgstr "Невозможно авторизировать этого персонажа. "
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "Регистрационный токен просрочен."
|
msgstr "Регистрационный токен просрочен."
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
msgstr "Отправить подтверждающее письмо. Пожалуйста, подтвердите почту. "
|
msgstr "Отправить подтверждающее письмо. Пожалуйста, подтвердите почту. "
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr "Подтвердите Ваш email адрес. Зайти для подтверждения. "
|
msgstr "Подтвердите Ваш email адрес. Зайти для подтверждения. "
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "Регистрация нового аккаунта сейчас невозможна."
|
msgstr "Регистрация новых аккаунтов в настоящее время невозможна."
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
msgid "Corporation Stats"
|
msgid "Corporation Stats"
|
||||||
@@ -226,16 +228,16 @@ msgstr "Последнее обновление: "
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "Персонаж"
|
msgstr "Персонаж"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -326,7 +328,7 @@ msgstr "Добавить сюда"
|
|||||||
|
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
|
||||||
msgid "before attempting to click fleet attendance links."
|
msgid "before attempting to click fleet attendance links."
|
||||||
msgstr "перед вступлением проверте содержимое"
|
msgstr "перед вступлением проверьте содержимое"
|
||||||
|
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:6
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:6
|
||||||
msgid "Create Fatlink"
|
msgid "Create Fatlink"
|
||||||
@@ -548,36 +550,35 @@ msgstr "Флотовое участие зарегистрированно."
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "ФлАк ссылка устарела"
|
msgstr "ФлАк ссылка устарела"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr "Управление Группой"
|
msgstr "Управление Группой"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr "Записи безопасности"
|
msgstr "Записи безопасности"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Назад"
|
msgstr "Назад"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "Дата / Время"
|
msgstr "Дата / Время"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr "Запрос от"
|
msgstr "Запрос от"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Тип"
|
msgstr "Тип"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -588,11 +589,19 @@ msgstr "Тип"
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr "Действие"
|
msgstr "Действие"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr "Исполнитель"
|
msgstr "Исполнитель"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "Нет вхождений в эту группу"
|
msgstr "Нет вхождений в эту группу"
|
||||||
|
|
||||||
@@ -600,22 +609,24 @@ msgstr "Нет вхождений в эту группу"
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr "Групповые Участники"
|
msgstr "Групповые Участники"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr "Портрет"
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "Корпорация"
|
msgstr "Корпорация"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "Исключить из группы"
|
msgstr "Исключить из группы"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "Нет участников в группе"
|
msgstr "Нет участников в группе"
|
||||||
|
|
||||||
@@ -623,18 +634,18 @@ msgstr "Нет участников в группе"
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr "Участники группы"
|
msgstr "Участники группы"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Группы"
|
msgstr "Группы"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Описание"
|
msgstr "Описание"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -643,36 +654,36 @@ msgstr "Описание"
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr "Статус"
|
msgstr "Статус"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "Число участников"
|
msgstr "Число участников"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "Скрытые"
|
msgstr "Скрытые"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "Открыть"
|
msgstr "Открыть"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "Запрошено"
|
msgstr "Запрошено"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr "Посмотреть участников"
|
msgstr "Посмотреть участников"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr "Проверить участников"
|
msgstr "Проверить участников"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr "Скопировать ссылку подключения"
|
msgstr "Скопировать ссылку подключения"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr "Нет групп в списке"
|
msgstr "Нет групп в списке"
|
||||||
|
|
||||||
@@ -681,19 +692,19 @@ msgstr "Нет групп в списке"
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "Доступные группы"
|
msgstr "Доступные группы"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "Покинуть"
|
msgstr "Покинуть"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "Присоединиться"
|
msgstr "Присоединиться"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "Запрос"
|
msgstr "Запрос"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "Нет доступных групп."
|
msgstr "Нет доступных групп."
|
||||||
|
|
||||||
@@ -705,24 +716,24 @@ msgstr "Управление Группами"
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr "Запрос на присоединение"
|
msgstr "Запрос на присоединение"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr "Запрос на Выход"
|
msgstr "Запрос на Выход"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "Группа"
|
msgstr "Группа"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "Принять"
|
msgstr "Принять"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "Сбросить"
|
msgstr "Сбросить"
|
||||||
@@ -731,19 +742,19 @@ msgstr "Сбросить"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "Нет групповых запросов на вступление"
|
msgstr "Нет групповых запросов на вступление"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "Нет групповых запросов на выход"
|
msgstr "Нет групповых запросов на выход"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr "Проложить маршрут"
|
msgstr "Проложить маршрут"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr "Групповой запрос"
|
msgstr "Групповой запрос"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr "Групповое участие"
|
msgstr "Групповое участие"
|
||||||
|
|
||||||
@@ -1029,7 +1040,7 @@ msgstr "Не прочитанно"
|
|||||||
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:18
|
#: allianceauth/notifications/templates/notifications/list.html:18
|
||||||
msgid "Read"
|
msgid "Read"
|
||||||
msgstr "Прочитать"
|
msgstr "Прочитано"
|
||||||
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:22
|
#: allianceauth/notifications/templates/notifications/list.html:22
|
||||||
msgid "Mark All Read"
|
msgid "Mark All Read"
|
||||||
@@ -1137,7 +1148,7 @@ msgstr "Таймера Флотовых операций"
|
|||||||
#: allianceauth/optimer/templates/optimer/management.html:21
|
#: allianceauth/optimer/templates/optimer/management.html:21
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:23
|
#: allianceauth/timerboard/templates/timerboard/view.html:23
|
||||||
msgid "Current Eve Time:"
|
msgid "Current Eve Time:"
|
||||||
msgstr "ET"
|
msgstr "Текущий EVE Time:"
|
||||||
|
|
||||||
#: allianceauth/optimer/templates/optimer/management.html:27
|
#: allianceauth/optimer/templates/optimer/management.html:27
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:189
|
#: allianceauth/timerboard/templates/timerboard/view.html:189
|
||||||
@@ -1244,7 +1255,7 @@ msgstr "{} Пароль успешно обновлен."
|
|||||||
|
|
||||||
#: allianceauth/services/auth_hooks.py:11
|
#: allianceauth/services/auth_hooks.py:11
|
||||||
msgid "Services"
|
msgid "Services"
|
||||||
msgstr "Сервисные услуги"
|
msgstr "Подключение сервисов"
|
||||||
|
|
||||||
#: allianceauth/services/forms.py:6
|
#: allianceauth/services/forms.py:6
|
||||||
msgid "Name of Fleet:"
|
msgid "Name of Fleet:"
|
||||||
@@ -1312,11 +1323,9 @@ msgstr "Discord персонаж отключен"
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ваш доступ на сервер Discord был отменен. Если Вы считаете что по ошибке, "
|
|
||||||
"пожалуйста, свяжитесь с СЕО."
|
|
||||||
|
|
||||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
|
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
|
||||||
msgid "Join the Discord server"
|
msgid "Join the Discord server"
|
||||||
@@ -1625,7 +1634,7 @@ msgstr "Домен"
|
|||||||
|
|
||||||
#: allianceauth/srp/auth_hooks.py:12
|
#: allianceauth/srp/auth_hooks.py:12
|
||||||
msgid "Ship Replacement"
|
msgid "Ship Replacement"
|
||||||
msgstr "Замена корабля"
|
msgstr "Компенсация корабля"
|
||||||
|
|
||||||
#: allianceauth/srp/form.py:7
|
#: allianceauth/srp/form.py:7
|
||||||
#: allianceauth/srp/templates/srp/management.html:38
|
#: allianceauth/srp/templates/srp/management.html:38
|
||||||
@@ -1974,14 +1983,14 @@ msgstr "Прочие"
|
|||||||
#: allianceauth/timerboard/templates/timerboard/view.html:220
|
#: allianceauth/timerboard/templates/timerboard/view.html:220
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:388
|
#: allianceauth/timerboard/templates/timerboard/view.html:388
|
||||||
msgid "Friendly"
|
msgid "Friendly"
|
||||||
msgstr "Дружествен"
|
msgstr "Дружественный"
|
||||||
|
|
||||||
#: allianceauth/timerboard/form.py:55
|
#: allianceauth/timerboard/form.py:55
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:53
|
#: allianceauth/timerboard/templates/timerboard/view.html:53
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:215
|
#: allianceauth/timerboard/templates/timerboard/view.html:215
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:383
|
#: allianceauth/timerboard/templates/timerboard/view.html:383
|
||||||
msgid "Hostile"
|
msgid "Hostile"
|
||||||
msgstr "Заложник"
|
msgstr "Вражеский"
|
||||||
|
|
||||||
#: allianceauth/timerboard/form.py:56
|
#: allianceauth/timerboard/form.py:56
|
||||||
#: allianceauth/timerboard/templates/timerboard/view.html:63
|
#: allianceauth/timerboard/templates/timerboard/view.html:63
|
||||||
@@ -2083,3 +2092,6 @@ msgstr "Добавлен таймер в %(system)s на %(time)s."
|
|||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr "Изменения сохранены"
|
msgstr "Изменения сохранены"
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr "Портрет"
|
||||||
|
|||||||
Binary file not shown.
@@ -4,18 +4,18 @@
|
|||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
|
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||||
# Jesse . <sgeine@hotmail.com>, 2020
|
# Jesse . <sgeine@hotmail.com>, 2020
|
||||||
# Aaron BuBu <351793078@qq.com>, 2020
|
# Aaron BuBu <351793078@qq.com>, 2020
|
||||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
"POT-Creation-Date: 2020-11-20 05:33+0000\n"
|
||||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||||
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
|
"Last-Translator: Aaron BuBu <351793078@qq.com>, 2020\n"
|
||||||
"Language-Team: Chinese Simplified (https://www.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n"
|
"Language-Team: Chinese Simplified (https://www.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -79,7 +79,7 @@ msgstr "角色"
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:45
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:34
|
||||||
@@ -159,23 +159,23 @@ msgstr "添加%(name)s到您的账户失败:他们已经在一个账户中了"
|
|||||||
msgid "Unable to authenticate as the selected character."
|
msgid "Unable to authenticate as the selected character."
|
||||||
msgstr "无法作为选定的角色进行身份验证"
|
msgstr "无法作为选定的角色进行身份验证"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:146
|
#: allianceauth/authentication/views.py:151
|
||||||
msgid "Registration token has expired."
|
msgid "Registration token has expired."
|
||||||
msgstr "注册令牌过期。"
|
msgstr "注册令牌过期。"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:201
|
#: allianceauth/authentication/views.py:206
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sent confirmation email. Please follow the link to confirm your email "
|
"Sent confirmation email. Please follow the link to confirm your email "
|
||||||
"address."
|
"address."
|
||||||
msgstr "已经发送了确认邮件。请按照链接确定您的电邮地址"
|
msgstr "已经发送了确认邮件。请按照链接确定您的电邮地址"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:206
|
#: allianceauth/authentication/views.py:211
|
||||||
msgid "Confirmed your email address. Please login to continue."
|
msgid "Confirmed your email address. Please login to continue."
|
||||||
msgstr "已确认您的电邮地址。请登录以继续"
|
msgstr "已确认您的电邮地址。请登录以继续"
|
||||||
|
|
||||||
#: allianceauth/authentication/views.py:211
|
#: allianceauth/authentication/views.py:216
|
||||||
msgid "Registraion of new accounts it not allowed at this time."
|
msgid "Registration of new accounts is not allowed at this time."
|
||||||
msgstr "现在不允许注册新账户。"
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/corputils/auth_hooks.py:10
|
#: allianceauth/corputils/auth_hooks.py:10
|
||||||
msgid "Corporation Stats"
|
msgid "Corporation Stats"
|
||||||
@@ -222,16 +222,16 @@ msgstr "最后一次更新"
|
|||||||
#: allianceauth/corputils/templates/corputils/search.html:13
|
#: allianceauth/corputils/templates/corputils/search.html:13
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:24
|
||||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:109
|
||||||
msgid "Character"
|
msgid "Character"
|
||||||
msgstr "角色"
|
msgstr "角色"
|
||||||
|
|
||||||
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
#: allianceauth/corputils/templates/corputils/corpstats.html:76
|
||||||
#: allianceauth/corputils/templates/corputils/search.html:14
|
#: allianceauth/corputils/templates/corputils/search.html:14
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:27
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:84
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:129
|
||||||
@@ -538,36 +538,35 @@ msgstr "成功注册舰队PAP"
|
|||||||
msgid "FAT link has expired."
|
msgid "FAT link has expired."
|
||||||
msgstr "PAP链接已过期"
|
msgstr "PAP链接已过期"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
#: allianceauth/groupmanagement/auth_hooks.py:17
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:14
|
||||||
msgid "Group Management"
|
msgid "Group Management"
|
||||||
msgstr "用户组管理"
|
msgstr "用户组管理"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:14
|
||||||
msgid "Audit Log"
|
msgid "Audit Log"
|
||||||
msgstr "审计日志"
|
msgstr "审计日志"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:20
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:21
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "返回"
|
msgstr "返回"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:28
|
||||||
msgid "Date/Time"
|
msgid "Date/Time"
|
||||||
msgstr "日期/时间"
|
msgstr "日期/时间"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:26
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
||||||
msgid "Requestor"
|
msgid "Requestor"
|
||||||
msgstr "申请人"
|
msgstr "申请人"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:32
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "类型"
|
msgstr "类型"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:33
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:17
|
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:37
|
#: allianceauth/notifications/templates/notifications/list.html:37
|
||||||
#: allianceauth/notifications/templates/notifications/list.html:69
|
#: allianceauth/notifications/templates/notifications/list.html:69
|
||||||
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
#: allianceauth/optimer/templates/optimer/fleetoptable.html:18
|
||||||
@@ -578,11 +577,19 @@ msgstr "类型"
|
|||||||
msgid "Action"
|
msgid "Action"
|
||||||
msgstr "操作"
|
msgstr "操作"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:34
|
||||||
msgid "Actor"
|
msgid "Actor"
|
||||||
msgstr "操作者"
|
msgstr "操作者"
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:47
|
||||||
|
msgid "Removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:59
|
||||||
|
msgid "All times displayed are EVE/UTC."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:66
|
||||||
msgid "No entries found for this group."
|
msgid "No entries found for this group."
|
||||||
msgstr "这一用户组下面没有任何条目呀"
|
msgstr "这一用户组下面没有任何条目呀"
|
||||||
|
|
||||||
@@ -590,22 +597,24 @@ msgstr "这一用户组下面没有任何条目呀"
|
|||||||
msgid "Group Members"
|
msgid "Group Members"
|
||||||
msgstr "群组成员"
|
msgstr "群组成员"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:28
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:31
|
||||||
msgid "Portrait"
|
|
||||||
msgstr "人物头像"
|
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "组织"
|
msgstr "组织"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:64
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:61
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:78
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:136
|
||||||
|
msgid "(unknown)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:66
|
||||||
msgid "Remove from group"
|
msgid "Remove from group"
|
||||||
msgstr "从用户组中移除"
|
msgstr "从用户组中移除"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:76
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:81
|
||||||
msgid "No group members to list."
|
msgid "No group members to list."
|
||||||
msgstr "用户组里没人呀,你叫我怎么列"
|
msgstr "用户组里没人呀,你叫我怎么列"
|
||||||
|
|
||||||
@@ -613,18 +622,18 @@ msgstr "用户组里没人呀,你叫我怎么列"
|
|||||||
msgid "Groups Membership"
|
msgid "Groups Membership"
|
||||||
msgstr "用户组成员"
|
msgstr "用户组成员"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:15
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "群组"
|
msgstr "群组"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "描述"
|
msgstr "描述"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:26
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||||
@@ -633,36 +642,36 @@ msgstr "描述"
|
|||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr "状态"
|
msgstr "状态"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:25
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:27
|
||||||
msgid "Member Count"
|
msgid "Member Count"
|
||||||
msgstr "成员数量"
|
msgstr "成员数量"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:38
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:43
|
||||||
msgid "Hidden"
|
msgid "Hidden"
|
||||||
msgstr "已隐藏"
|
msgstr "已隐藏"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:40
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
#: allianceauth/templates/allianceauth/admin-status/overview.html:12
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "公开"
|
msgstr "公开"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:42
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:47
|
||||||
msgid "Requestable"
|
msgid "Requestable"
|
||||||
msgstr "可申请"
|
msgstr "可申请"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:50
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||||
msgid "View Members"
|
msgid "View Members"
|
||||||
msgstr "查看成员"
|
msgstr "查看成员"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:60
|
||||||
msgid "Audit Members"
|
msgid "Audit Members"
|
||||||
msgstr "编辑成员"
|
msgstr "编辑成员"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64
|
||||||
msgid "Copy Direct Join Link"
|
msgid "Copy Direct Join Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:75
|
||||||
msgid "No groups to list."
|
msgid "No groups to list."
|
||||||
msgstr "无可用组"
|
msgstr "无可用组"
|
||||||
|
|
||||||
@@ -671,19 +680,19 @@ msgstr "无可用组"
|
|||||||
msgid "Available Groups"
|
msgid "Available Groups"
|
||||||
msgstr "可用组"
|
msgstr "可用组"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:29
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:30
|
||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "离开"
|
msgstr "离开"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:39
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:40
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr "加入"
|
msgstr "加入"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:43
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:44
|
||||||
msgid "Request"
|
msgid "Request"
|
||||||
msgstr "申请"
|
msgstr "申请"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:58
|
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:59
|
||||||
msgid "No groups available."
|
msgid "No groups available."
|
||||||
msgstr "没有可用用户组"
|
msgstr "没有可用用户组"
|
||||||
|
|
||||||
@@ -695,24 +704,24 @@ msgstr "用户组管理"
|
|||||||
msgid "Join Requests"
|
msgid "Join Requests"
|
||||||
msgstr "入组的请求"
|
msgstr "入组的请求"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:34
|
||||||
msgid "Leave Requests"
|
msgid "Leave Requests"
|
||||||
msgstr "离组的请求"
|
msgstr "离组的请求"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||||
#: allianceauth/services/modules/openfire/forms.py:6
|
#: allianceauth/services/modules/openfire/forms.py:6
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "用户组"
|
msgstr "用户组"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:84
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "接受"
|
msgstr "接受"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:146
|
||||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||||
msgid "Reject"
|
msgid "Reject"
|
||||||
msgstr "拒绝"
|
msgstr "拒绝"
|
||||||
@@ -721,19 +730,19 @@ msgstr "拒绝"
|
|||||||
msgid "No group add requests."
|
msgid "No group add requests."
|
||||||
msgstr "没有加入用户组的请求,小老弟你是不是摇不到人"
|
msgstr "没有加入用户组的请求,小老弟你是不是摇不到人"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:155
|
||||||
msgid "No group leave requests."
|
msgid "No group leave requests."
|
||||||
msgstr "没有离开用户组的请求,小老弟你人缘可以啊?"
|
msgstr "没有离开用户组的请求,小老弟你人缘可以啊?"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:10
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:9
|
||||||
msgid "Toggle navigation"
|
msgid "Toggle navigation"
|
||||||
msgstr "打开导航栏"
|
msgstr "打开导航栏"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:20
|
||||||
msgid "Group Requests"
|
msgid "Group Requests"
|
||||||
msgstr "用户组请求"
|
msgstr "用户组请求"
|
||||||
|
|
||||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:24
|
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:23
|
||||||
msgid "Group Membership"
|
msgid "Group Membership"
|
||||||
msgstr "用户组成员"
|
msgstr "用户组成员"
|
||||||
|
|
||||||
@@ -1298,7 +1307,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: allianceauth/services/modules/discord/models.py:227
|
#: allianceauth/services/modules/discord/models.py:227
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||||
"was a mistake, please contact an admin."
|
"was a mistake, please contact an admin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2052,3 +2061,6 @@ msgstr "已经把%(system)s星系里%(time)s的时间节点设置好了!CTA!
|
|||||||
#: allianceauth/timerboard/views.py:83
|
#: allianceauth/timerboard/views.py:83
|
||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr "保存至新的计划表"
|
msgstr "保存至新的计划表"
|
||||||
|
|
||||||
|
#~ msgid "Portrait"
|
||||||
|
#~ msgstr "人物头像"
|
||||||
|
|||||||
@@ -1,22 +1,9 @@
|
|||||||
default_app_config = 'allianceauth.notifications.apps.NotificationsConfig'
|
default_app_config = 'allianceauth.notifications.apps.NotificationsConfig'
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
MAX_NOTIFICATIONS = 50
|
|
||||||
|
|
||||||
|
|
||||||
def notify(user, title, message=None, level='info'):
|
def notify(
|
||||||
|
user: object, title: str, message: str = None, level: str = 'info'
|
||||||
|
) -> None:
|
||||||
|
"""Sends a new notification to user. Convenience function to manager pendant."""
|
||||||
from .models import Notification
|
from .models import Notification
|
||||||
if Notification.objects.filter(user=user).count() > MAX_NOTIFICATIONS:
|
Notification.objects.notify_user(user, title, message, level)
|
||||||
for n in Notification.objects.filter(user=user)[MAX_NOTIFICATIONS-1:]:
|
|
||||||
n.delete()
|
|
||||||
notif = Notification()
|
|
||||||
notif.user = user
|
|
||||||
notif.title = title
|
|
||||||
if not message:
|
|
||||||
message = title
|
|
||||||
notif.message = message
|
|
||||||
notif.level = level
|
|
||||||
notif.save()
|
|
||||||
logger.info("Created notification %s" % notif)
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
from .models import Notification
|
|
||||||
from django.core.cache import cache
|
|
||||||
|
|
||||||
def user_notification_count(request):
|
|
||||||
user_id = request.user.id
|
|
||||||
notification_count = cache.get("u-note:{}".format(user_id), -1)
|
|
||||||
if notification_count<0:
|
|
||||||
notification_count = Notification.objects.filter(user__id=user_id).filter(viewed=False).count()
|
|
||||||
cache.set("u-note:{}".format(user_id),notification_count,5)
|
|
||||||
|
|
||||||
return {'notifications': notification_count}
|
|
||||||
101
allianceauth/notifications/managers.py
Normal file
101
allianceauth/notifications/managers.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.cache import cache
|
||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationQuerySet(models.QuerySet):
|
||||||
|
"""Custom QuerySet for Notification model"""
|
||||||
|
|
||||||
|
def update(self, *args, **kwargs):
|
||||||
|
# overriden update to ensure cache is invaidated on very call
|
||||||
|
super().update(*args, **kwargs)
|
||||||
|
user_pks = set(self.select_related("user").values_list('user__pk', flat=True))
|
||||||
|
for user_pk in user_pks:
|
||||||
|
NotificationManager.invalidate_user_notification_cache(user_pk)
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationManager(models.Manager):
|
||||||
|
|
||||||
|
USER_NOTIFICATION_COUNT_PREFIX = 'USER_NOTIFICATION_COUNT'
|
||||||
|
USER_NOTIFICATION_COUNT_CACHE_DURATION = 86_400
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return NotificationQuerySet(self.model, using=self._db)
|
||||||
|
|
||||||
|
def notify_user(
|
||||||
|
self, user: object, title: str, message: str = None, level: str = 'info'
|
||||||
|
) -> object:
|
||||||
|
"""Sends a new notification to user. Returns newly created notification object.
|
||||||
|
"""
|
||||||
|
max_notifications = self._max_notifications_per_user()
|
||||||
|
if self.filter(user=user).count() >= max_notifications:
|
||||||
|
to_be_deleted_qs = self.filter(user=user).order_by(
|
||||||
|
"-timestamp"
|
||||||
|
)[max_notifications - 1:]
|
||||||
|
for notification in to_be_deleted_qs:
|
||||||
|
notification.delete()
|
||||||
|
|
||||||
|
if not message:
|
||||||
|
message = title
|
||||||
|
|
||||||
|
obj = self.create(user=user, title=title, message=message, level=level)
|
||||||
|
logger.info("Created notification %s", obj)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def _max_notifications_per_user(self):
|
||||||
|
"""return the maximum number of notifications allowed per user"""
|
||||||
|
max_notifications = getattr(settings, 'NOTIFICATIONS_MAX_PER_USER', None)
|
||||||
|
if (
|
||||||
|
max_notifications is None
|
||||||
|
or not isinstance(max_notifications, int)
|
||||||
|
or max_notifications < 0
|
||||||
|
):
|
||||||
|
logger.warning(
|
||||||
|
'NOTIFICATIONS_MAX_PER_USER setting is invalid. Using default.'
|
||||||
|
)
|
||||||
|
max_notifications = self.model.NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
||||||
|
|
||||||
|
return max_notifications
|
||||||
|
|
||||||
|
def user_unread_count(self, user_pk: int) -> int:
|
||||||
|
"""returns the cached unread count for a user given by user PK
|
||||||
|
|
||||||
|
Will return -1 if user can not be found
|
||||||
|
"""
|
||||||
|
cache_key = self._user_notification_cache_key(user_pk)
|
||||||
|
unread_count = cache.get(key=cache_key)
|
||||||
|
if not unread_count:
|
||||||
|
try:
|
||||||
|
user = User.objects.get(pk=user_pk)
|
||||||
|
except User.DoesNotExist:
|
||||||
|
unread_count = -1
|
||||||
|
else:
|
||||||
|
logger.debug(
|
||||||
|
'Updating notification cache for user with pk %s', user_pk
|
||||||
|
)
|
||||||
|
unread_count = user.notification_set.filter(viewed=False).count()
|
||||||
|
cache.set(
|
||||||
|
key=cache_key,
|
||||||
|
value=unread_count,
|
||||||
|
timeout=self.USER_NOTIFICATION_COUNT_CACHE_DURATION
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.debug(
|
||||||
|
'Returning notification count from cache for user with pk %s', user_pk
|
||||||
|
)
|
||||||
|
|
||||||
|
return unread_count
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def invalidate_user_notification_cache(cls, user_pk: int) -> None:
|
||||||
|
cache.delete(key=cls._user_notification_cache_key(user_pk))
|
||||||
|
logger.debug('Invalided notification cache for user with pk %s', user_pk)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _user_notification_cache_key(cls, user_pk: int) -> str:
|
||||||
|
return f'{cls.USER_NOTIFICATION_COUNT_PREFIX}_{user_pk}'
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Generated by Django 3.1.5 on 2021-01-07 21:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('notifications', '0003_make_strings_more_stringy'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='notification',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='notification',
|
||||||
|
name='timestamp',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, db_index=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='notification',
|
||||||
|
name='viewed',
|
||||||
|
field=models.BooleanField(db_index=True, default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
import logging
|
|
||||||
|
from .managers import NotificationManager
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Notification(models.Model):
|
class Notification(models.Model):
|
||||||
|
"""Notification to a user within Auth"""
|
||||||
|
|
||||||
|
NOTIFICATIONS_MAX_PER_USER_DEFAULT = 50
|
||||||
|
NOTIFICATIONS_REFRESH_TIME_DEFAULT = 30
|
||||||
|
|
||||||
LEVEL_CHOICES = (
|
LEVEL_CHOICES = (
|
||||||
('danger', 'CRITICAL'),
|
('danger', 'CRITICAL'),
|
||||||
('danger', 'ERROR'),
|
('danger', 'ERROR'),
|
||||||
@@ -18,19 +26,41 @@ class Notification(models.Model):
|
|||||||
level = models.CharField(choices=LEVEL_CHOICES, max_length=10)
|
level = models.CharField(choices=LEVEL_CHOICES, max_length=10)
|
||||||
title = models.CharField(max_length=254)
|
title = models.CharField(max_length=254)
|
||||||
message = models.TextField()
|
message = models.TextField()
|
||||||
timestamp = models.DateTimeField(auto_now_add=True)
|
timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
|
||||||
viewed = models.BooleanField(default=False)
|
viewed = models.BooleanField(default=False, db_index=True)
|
||||||
|
|
||||||
def view(self):
|
objects = NotificationManager()
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return "%s: %s" % (self.user, self.title)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
# overriden save to ensure cache is invaidated on very call
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
# overriden delete to ensure cache is invaidated on very call
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
Notification.objects.invalidate_user_notification_cache(self.user.pk)
|
||||||
|
|
||||||
|
def mark_viewed(self) -> None:
|
||||||
|
"""mark notification as viewed"""
|
||||||
logger.info("Marking notification as viewed: %s" % self)
|
logger.info("Marking notification as viewed: %s" % self)
|
||||||
self.viewed = True
|
self.viewed = True
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def __str__(self):
|
def set_level(self, level_name: str) -> None:
|
||||||
return "%s: %s" % (self.user, self.title)
|
"""set notification level according to level name, e.g. 'CRITICAL'
|
||||||
|
|
||||||
|
raised exception on invalid level names
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
new_level = [
|
||||||
|
item[0] for item in self.LEVEL_CHOICES if item[1] == level_name
|
||||||
|
][0]
|
||||||
|
except IndexError:
|
||||||
|
raise ValueError('Invalid level name: %s' % level_name)
|
||||||
|
|
||||||
def set_level(self, level):
|
self.level = new_level
|
||||||
self.level = [item[0] for item in self.LEVEL_CHOICES if item[1] == level][0]
|
self.save()
|
||||||
|
|
||||||
class Meta:
|
|
||||||
ordering = ['-timestamp']
|
|
||||||
|
|||||||
0
allianceauth/notifications/templatetags/__init__.py
Normal file
0
allianceauth/notifications/templatetags/__init__.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
"""Templatetags for notifications
|
||||||
|
|
||||||
|
These template tags are required to enable the notifications refresh functionality
|
||||||
|
in the browser.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from allianceauth.notifications.models import Notification
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def user_unread_notification_count(user: object) -> int:
|
||||||
|
"""returns the number of unread notifications for user
|
||||||
|
|
||||||
|
Will return -1 on error
|
||||||
|
"""
|
||||||
|
if not isinstance(user, User):
|
||||||
|
unread_count = -1
|
||||||
|
else:
|
||||||
|
unread_count = Notification.objects.user_unread_count(user.pk)
|
||||||
|
|
||||||
|
return unread_count
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def notifications_refresh_time() -> int:
|
||||||
|
refresh_time = getattr(settings, 'NOTIFICATIONS_REFRESH_TIME', Notification.NOTIFICATIONS_REFRESH_TIME_DEFAULT)
|
||||||
|
if (not isinstance(refresh_time, int) or refresh_time < 0):
|
||||||
|
logger.warning('NOTIFICATIONS_REFRESH_TIME setting is invalid. Using default.')
|
||||||
|
refresh_time = Notification.NOTIFICATIONS_REFRESH_TIME_DEFAULT
|
||||||
|
|
||||||
|
return refresh_time
|
||||||
28
allianceauth/notifications/tests/test_init.py
Normal file
28
allianceauth/notifications/tests/test_init.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
|
from .. import notify
|
||||||
|
from ..models import Notification
|
||||||
|
|
||||||
|
MODULE_PATH = 'allianceauth.notifications'
|
||||||
|
|
||||||
|
|
||||||
|
class TestUserNotificationCount(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user,
|
||||||
|
'Magic Mike',
|
||||||
|
'1',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_can_notify(self):
|
||||||
|
notify(self.user, 'dummy')
|
||||||
|
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
||||||
206
allianceauth/notifications/tests/test_managers.py
Normal file
206
allianceauth/notifications/tests/test_managers.py
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
from ..models import Notification
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_PATH = 'allianceauth.notifications.models'
|
||||||
|
|
||||||
|
NOTIFICATIONS_MAX_PER_USER_DEFAULT = 42
|
||||||
|
|
||||||
|
|
||||||
|
class TestQuerySet(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user_1 = AuthUtils.create_user('Peter Parker')
|
||||||
|
cls.user_2 = AuthUtils.create_user('Clark Kent')
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
||||||
|
def test_update_will_invalidate_cache(
|
||||||
|
self, mock_invalidate_user_notification_cache
|
||||||
|
):
|
||||||
|
Notification.objects.notify_user(self.user_1, 'dummy_1')
|
||||||
|
Notification.objects.notify_user(self.user_2, 'dummy_2')
|
||||||
|
Notification.objects.update(viewed=True)
|
||||||
|
self.assertEquals(mock_invalidate_user_notification_cache.call_count, 2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestUserNotify(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user,
|
||||||
|
'Magic Mike',
|
||||||
|
'1',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_can_notify(self):
|
||||||
|
title = 'dummy_title'
|
||||||
|
message = 'dummy message'
|
||||||
|
level = 'danger'
|
||||||
|
Notification.objects.notify_user(self.user, title, message, level)
|
||||||
|
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
||||||
|
obj = Notification.objects.first()
|
||||||
|
self.assertEqual(obj.user, self.user)
|
||||||
|
self.assertEqual(obj.title, title)
|
||||||
|
self.assertEqual(obj.message, message)
|
||||||
|
self.assertEqual(obj.level, level)
|
||||||
|
|
||||||
|
def test_use_message_as_title_if_missing(self):
|
||||||
|
title = 'dummy_title'
|
||||||
|
Notification.objects.notify_user(self.user, title)
|
||||||
|
self.assertEqual(Notification.objects.filter(user=self.user).count(), 1)
|
||||||
|
obj = Notification.objects.first()
|
||||||
|
self.assertEqual(obj.user, self.user)
|
||||||
|
self.assertEqual(obj.title, title)
|
||||||
|
self.assertEqual(obj.message, title)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_MAX_PER_USER=3)
|
||||||
|
def test_remove_when_too_many_notifications(self):
|
||||||
|
Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
obj_2 = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
obj_3 = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
obj_4 = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
expected = {obj_2.pk, obj_3.pk, obj_4.pk}
|
||||||
|
result = set(
|
||||||
|
Notification.objects.filter(user=self.user).values_list("pk", flat=True)
|
||||||
|
)
|
||||||
|
self.assertSetEqual(result, expected)
|
||||||
|
obj_5 = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
expected = {obj_3.pk, obj_4.pk, obj_5.pk}
|
||||||
|
result = set(
|
||||||
|
Notification.objects.filter(user=self.user).values_list("pk", flat=True)
|
||||||
|
)
|
||||||
|
self.assertSetEqual(result, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
MODULE_PATH + '.Notification.NOTIFICATIONS_MAX_PER_USER_DEFAULT',
|
||||||
|
NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
||||||
|
)
|
||||||
|
class TestMaxNotificationsPerUser(TestCase):
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_MAX_PER_USER=None)
|
||||||
|
def test_reset_to_default_if_not_defined(self):
|
||||||
|
result = Notification.objects._max_notifications_per_user()
|
||||||
|
expected = NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_MAX_PER_USER='11')
|
||||||
|
def test_reset_to_default_if_not_int(self):
|
||||||
|
result = Notification.objects._max_notifications_per_user()
|
||||||
|
expected = NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_MAX_PER_USER=-1)
|
||||||
|
def test_reset_to_default_if_lt_zero(self):
|
||||||
|
result = Notification.objects._max_notifications_per_user()
|
||||||
|
expected = NOTIFICATIONS_MAX_PER_USER_DEFAULT
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@patch('allianceauth.notifications.managers.cache')
|
||||||
|
class TestUnreadCount(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user_1 = AuthUtils.create_user('magic_mike')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user_1,
|
||||||
|
'Magic Mike',
|
||||||
|
'1',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
|
||||||
|
# test notifications for mike
|
||||||
|
Notification.objects.all().delete()
|
||||||
|
Notification.objects.create(
|
||||||
|
user=cls.user_1,
|
||||||
|
level="INFO",
|
||||||
|
title="Job 1 Failed",
|
||||||
|
message="Because it was broken",
|
||||||
|
viewed=True
|
||||||
|
)
|
||||||
|
Notification.objects.create(
|
||||||
|
user=cls.user_1,
|
||||||
|
level="INFO",
|
||||||
|
title="Job 2 Failed",
|
||||||
|
message="Because it was broken"
|
||||||
|
)
|
||||||
|
Notification.objects.create(
|
||||||
|
user=cls.user_1,
|
||||||
|
level="INFO",
|
||||||
|
title="Job 3 Failed",
|
||||||
|
message="Because it was broken"
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.user_2 = AuthUtils.create_user('teh_kid')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user_2,
|
||||||
|
'The Kid', '2',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Notifications for kid
|
||||||
|
Notification.objects.create(
|
||||||
|
user=cls.user_2,
|
||||||
|
level="INFO",
|
||||||
|
title="Job 6 Failed",
|
||||||
|
message="Because it was broken"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_update_cache_when_not_in_cache(self, mock_cache):
|
||||||
|
mock_cache.get.return_value = None
|
||||||
|
|
||||||
|
result = Notification.objects.user_unread_count(self.user_1.pk)
|
||||||
|
expected = 2
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertTrue(mock_cache.set.called)
|
||||||
|
args, kwargs = mock_cache.set.call_args
|
||||||
|
self.assertEqual(
|
||||||
|
kwargs['key'],
|
||||||
|
Notification.objects._user_notification_cache_key(self.user_1.pk)
|
||||||
|
)
|
||||||
|
self.assertEqual(kwargs['value'], expected)
|
||||||
|
|
||||||
|
def test_return_from_cache_when_in_cache(self, mock_cache):
|
||||||
|
mock_cache.get.return_value = 42
|
||||||
|
result = Notification.objects.user_unread_count(self.user_1.pk)
|
||||||
|
expected = 42
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertFalse(mock_cache.set.called)
|
||||||
|
|
||||||
|
def test_return_error_code_when_user_not_found(self, mock_cache):
|
||||||
|
mock_cache.get.return_value = None
|
||||||
|
invalid_user_id = max([user.pk for user in User.objects.all()]) + 1
|
||||||
|
result = Notification.objects.user_unread_count(invalid_user_id)
|
||||||
|
expected = -1
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
self.assertFalse(mock_cache.set.called)
|
||||||
|
|
||||||
|
def test_can_invalidate_cache(self, mock_cache):
|
||||||
|
Notification.objects.invalidate_user_notification_cache(self.user_1.pk)
|
||||||
|
self.assertTrue(mock_cache.delete)
|
||||||
|
args, kwargs = mock_cache.delete.call_args
|
||||||
|
self.assertEqual(
|
||||||
|
kwargs['key'],
|
||||||
|
Notification.objects._user_notification_cache_key(self.user_1.pk)
|
||||||
|
)
|
||||||
73
allianceauth/notifications/tests/test_models.py
Normal file
73
allianceauth/notifications/tests/test_models.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
|
from ..models import Notification
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_PATH = 'allianceauth.notifications.models'
|
||||||
|
|
||||||
|
|
||||||
|
class TestUserNotify(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user,
|
||||||
|
'Magic Mike',
|
||||||
|
'1',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
||||||
|
def test_save_will_invalidate_cache(self, mock_invalidate_user_notification_cache):
|
||||||
|
obj = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
self.assertTrue(Notification.objects.filter(pk=obj.pk).exists())
|
||||||
|
self.assertEquals(mock_invalidate_user_notification_cache.call_count, 1)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.Notification.objects.invalidate_user_notification_cache')
|
||||||
|
def test_delete_will_invalidate_cache(
|
||||||
|
self, mock_invalidate_user_notification_cache
|
||||||
|
):
|
||||||
|
obj = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
obj.delete()
|
||||||
|
self.assertFalse(Notification.objects.filter(pk=obj.pk).exists())
|
||||||
|
self.assertEquals(mock_invalidate_user_notification_cache.call_count, 2)
|
||||||
|
|
||||||
|
def test_can_view(self):
|
||||||
|
obj = Notification.objects.notify_user(self.user, 'dummy')
|
||||||
|
self.assertFalse(obj.viewed)
|
||||||
|
obj.mark_viewed()
|
||||||
|
obj.refresh_from_db()
|
||||||
|
self.assertTrue(obj.viewed)
|
||||||
|
|
||||||
|
def test_can_set_level(self):
|
||||||
|
obj = Notification.objects.notify_user(self.user, 'dummy', level='info')
|
||||||
|
obj.set_level('ERROR')
|
||||||
|
obj.refresh_from_db()
|
||||||
|
self.assertEqual(obj.level, 'danger')
|
||||||
|
|
||||||
|
obj.set_level('CRITICAL')
|
||||||
|
obj.refresh_from_db()
|
||||||
|
self.assertEqual(obj.level, 'danger')
|
||||||
|
|
||||||
|
obj.set_level('WARN')
|
||||||
|
obj.refresh_from_db()
|
||||||
|
self.assertEqual(obj.level, 'warning')
|
||||||
|
|
||||||
|
obj.set_level('INFO')
|
||||||
|
obj.refresh_from_db()
|
||||||
|
self.assertEqual(obj.level, 'info')
|
||||||
|
|
||||||
|
obj.set_level('DEBUG')
|
||||||
|
obj.refresh_from_db()
|
||||||
|
self.assertEqual(obj.level, 'success')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
obj.set_level('XXX')
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
from unittest import mock
|
|
||||||
from django.test import TestCase
|
|
||||||
from allianceauth.notifications.context_processors import user_notification_count
|
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
|
||||||
from django.core.cache import cache
|
|
||||||
from allianceauth.notifications.models import Notification
|
|
||||||
|
|
||||||
class TestNotificationCount(TestCase):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpTestData(cls):
|
|
||||||
cls.user = AuthUtils.create_user('magic_mike')
|
|
||||||
AuthUtils.add_main_character(cls.user, 'Magic Mike', '1', corp_id='2', corp_name='Pole Riders', corp_ticker='PRIDE', alliance_id='3', alliance_name='RIDERS')
|
|
||||||
cls.user.profile.refresh_from_db()
|
|
||||||
|
|
||||||
### test notifications for mike
|
|
||||||
Notification.objects.all().delete()
|
|
||||||
Notification.objects.create(user=cls.user,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 1 Failed",
|
|
||||||
message="Because it was broken",
|
|
||||||
viewed=True)
|
|
||||||
Notification.objects.create(user=cls.user,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 2 Failed",
|
|
||||||
message="Because it was broken")
|
|
||||||
Notification.objects.create(user=cls.user,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 3 Failed",
|
|
||||||
message="Because it was broken")
|
|
||||||
Notification.objects.create(user=cls.user,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 4 Failed",
|
|
||||||
message="Because it was broken")
|
|
||||||
Notification.objects.create(user=cls.user,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 5 Failed",
|
|
||||||
message="Because it was broken")
|
|
||||||
Notification.objects.create(user=cls.user,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 6 Failed",
|
|
||||||
message="Because it was broken")
|
|
||||||
|
|
||||||
cls.user2 = AuthUtils.create_user('teh_kid')
|
|
||||||
AuthUtils.add_main_character(cls.user, 'The Kid', '2', corp_id='2', corp_name='Pole Riders', corp_ticker='PRIDE', alliance_id='3', alliance_name='RIDERS')
|
|
||||||
cls.user2.profile.refresh_from_db()
|
|
||||||
|
|
||||||
# Noitification for kid
|
|
||||||
Notification.objects.create(user=cls.user2,
|
|
||||||
level="INFO",
|
|
||||||
title="Job 6 Failed",
|
|
||||||
message="Because it was broken")
|
|
||||||
|
|
||||||
|
|
||||||
def test_no_cache(self):
|
|
||||||
mock_req = mock.MagicMock()
|
|
||||||
mock_req.user.id = self.user.id
|
|
||||||
|
|
||||||
cache.delete("u-note:{}".format(self.user.id)) # force the db to be hit
|
|
||||||
context_dict = user_notification_count(mock_req)
|
|
||||||
self.assertIsInstance(context_dict, dict)
|
|
||||||
self.assertEqual(context_dict.get('notifications'), 5) # 5 only
|
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('allianceauth.notifications.models.Notification.objects')
|
|
||||||
def test_cache(self, mock_foo):
|
|
||||||
mock_foo.filter.return_value = mock_foo
|
|
||||||
mock_foo.count.return_value = 5
|
|
||||||
mock_req = mock.MagicMock()
|
|
||||||
mock_req.user.id = self.user.id
|
|
||||||
|
|
||||||
cache.set("u-note:{}".format(self.user.id),10,5)
|
|
||||||
context_dict = user_notification_count(mock_req)
|
|
||||||
self.assertIsInstance(context_dict, dict)
|
|
||||||
self.assertEqual(context_dict.get('notifications'), 10) # cached value
|
|
||||||
self.assertEqual(mock_foo.called, 0) # ensure the DB was not hit
|
|
||||||
86
allianceauth/notifications/tests/test_templatetags.py
Normal file
86
allianceauth/notifications/tests/test_templatetags.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
from unittest.mock import patch, Mock
|
||||||
|
|
||||||
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
from ..templatetags.auth_notifications import (
|
||||||
|
user_unread_notification_count, notifications_refresh_time
|
||||||
|
)
|
||||||
|
|
||||||
|
MODULE_PATH = 'allianceauth.notifications.templatetags.auth_notifications'
|
||||||
|
|
||||||
|
NOTIFICATIONS_REFRESH_TIME_DEFAULT = 66
|
||||||
|
MY_NOTIFICATIONS_REFRESH_TIME = 23
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.Notification.objects.user_unread_count')
|
||||||
|
class TestUserNotificationCount(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user,
|
||||||
|
'Magic Mike',
|
||||||
|
'1',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_return_normal(self, mock_user_unread_count):
|
||||||
|
unread_count = 42
|
||||||
|
mock_user_unread_count.return_value = unread_count
|
||||||
|
|
||||||
|
result = user_unread_notification_count(self.user)
|
||||||
|
expected = unread_count
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
args, kwargs = mock_user_unread_count.call_args
|
||||||
|
self.assertEqual(args[0], self.user.pk)
|
||||||
|
|
||||||
|
def test_return_error_if_non_user(self, mock_user_unread_count):
|
||||||
|
unread_count = -1
|
||||||
|
mock_user_unread_count.return_value = unread_count
|
||||||
|
|
||||||
|
result = user_unread_notification_count('invalid')
|
||||||
|
expected = unread_count
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
MODULE_PATH + '.Notification.NOTIFICATIONS_REFRESH_TIME_DEFAULT',
|
||||||
|
NOTIFICATIONS_REFRESH_TIME_DEFAULT
|
||||||
|
)
|
||||||
|
class TestNotificationsRefreshTime(TestCase):
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_REFRESH_TIME=MY_NOTIFICATIONS_REFRESH_TIME)
|
||||||
|
def test_return_from_setting(self):
|
||||||
|
result = notifications_refresh_time()
|
||||||
|
expected = MY_NOTIFICATIONS_REFRESH_TIME
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_REFRESH_TIME=0)
|
||||||
|
def test_refresh_time_can_be_zero(self):
|
||||||
|
result = notifications_refresh_time()
|
||||||
|
expected = 0
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_REFRESH_TIME=None)
|
||||||
|
def test_return_default_refresh_time_if_not_exists(self):
|
||||||
|
result = notifications_refresh_time()
|
||||||
|
expected = NOTIFICATIONS_REFRESH_TIME_DEFAULT
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_REFRESH_TIME='33')
|
||||||
|
def test_return_default_refresh_time_if_not_int(self):
|
||||||
|
result = notifications_refresh_time()
|
||||||
|
expected = NOTIFICATIONS_REFRESH_TIME_DEFAULT
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
@override_settings(NOTIFICATIONS_REFRESH_TIME=-1)
|
||||||
|
def test_return_default_refresh_time_if_lt_0(self):
|
||||||
|
result = notifications_refresh_time()
|
||||||
|
expected = NOTIFICATIONS_REFRESH_TIME_DEFAULT
|
||||||
|
self.assertEqual(result, expected)
|
||||||
49
allianceauth/notifications/tests/test_views.py
Normal file
49
allianceauth/notifications/tests/test_views.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from unittest.mock import patch, Mock
|
||||||
|
|
||||||
|
from django.test import TestCase, RequestFactory
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
|
from ..views import user_notifications_count
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_PATH = 'allianceauth.notifications.views'
|
||||||
|
|
||||||
|
|
||||||
|
class TestViews(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user = AuthUtils.create_user('magic_mike')
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
cls.user,
|
||||||
|
'Magic Mike',
|
||||||
|
'1',
|
||||||
|
corp_id='2',
|
||||||
|
corp_name='Pole Riders',
|
||||||
|
corp_ticker='PRIDE',
|
||||||
|
alliance_id='3',
|
||||||
|
alliance_name='RIDERS'
|
||||||
|
)
|
||||||
|
cls.factory = RequestFactory()
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.Notification.objects.user_unread_count')
|
||||||
|
def test_user_notifications_count(self, mock_user_unread_count):
|
||||||
|
unread_count = 42
|
||||||
|
user_pk = 3
|
||||||
|
mock_user_unread_count.return_value = unread_count
|
||||||
|
|
||||||
|
request = self.factory.get(
|
||||||
|
reverse('notifications:user_notifications_count', args=[user_pk])
|
||||||
|
)
|
||||||
|
request.user = self.user
|
||||||
|
|
||||||
|
response = user_notifications_count(request, user_pk)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTrue(mock_user_unread_count.called)
|
||||||
|
expected = {'unread_count': unread_count}
|
||||||
|
result = json.loads(response.content.decode(response.charset))
|
||||||
|
self.assertDictEqual(result, expected)
|
||||||
@@ -9,4 +9,9 @@ urlpatterns = [
|
|||||||
url(r'^notifications/delete_all_read/$', views.delete_all_read, name='delete_all_read'),
|
url(r'^notifications/delete_all_read/$', views.delete_all_read, name='delete_all_read'),
|
||||||
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(
|
||||||
|
r'^user_notifications_count/(?P<user_pk>\d+)/$',
|
||||||
|
views.user_notifications_count,
|
||||||
|
name='user_notifications_count'
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
from django.shortcuts import render, get_object_or_404, redirect
|
import logging
|
||||||
from .models import Notification
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.http import JsonResponse
|
||||||
import logging
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from .models import Notification
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -11,9 +14,15 @@ logger = logging.getLogger(__name__)
|
|||||||
@login_required
|
@login_required
|
||||||
def notification_list(request):
|
def notification_list(request):
|
||||||
logger.debug("notification_list called by user %s" % request.user)
|
logger.debug("notification_list called by user %s" % request.user)
|
||||||
new_notifs = Notification.objects.filter(user=request.user).filter(viewed=False)
|
notifications_qs = Notification.objects.filter(user=request.user).order_by("-timestamp")
|
||||||
old_notifs = Notification.objects.filter(user=request.user).filter(viewed=True)
|
new_notifs = notifications_qs.filter(viewed=False)
|
||||||
logger.debug("User %s has %s unread and %s read notifications" % (request.user, len(new_notifs), len(old_notifs)))
|
old_notifs = notifications_qs.filter(viewed=True)
|
||||||
|
logger.debug(
|
||||||
|
"User %s has %s unread and %s read notifications",
|
||||||
|
request.user,
|
||||||
|
len(new_notifs),
|
||||||
|
len(old_notifs)
|
||||||
|
)
|
||||||
context = {
|
context = {
|
||||||
'read': old_notifs,
|
'read': old_notifs,
|
||||||
'unread': new_notifs,
|
'unread': new_notifs,
|
||||||
@@ -23,39 +32,53 @@ def notification_list(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def notification_view(request, notif_id):
|
def notification_view(request, notif_id):
|
||||||
logger.debug("notification_view called by user %s for notif_id %s" % (request.user, notif_id))
|
logger.debug(
|
||||||
|
"notification_view called by user %s for notif_id %s",
|
||||||
|
request.user,
|
||||||
|
notif_id
|
||||||
|
)
|
||||||
notif = get_object_or_404(Notification, pk=notif_id)
|
notif = get_object_or_404(Notification, pk=notif_id)
|
||||||
if notif.user == request.user:
|
if notif.user == request.user:
|
||||||
logger.debug("Providing notification for user %s" % request.user)
|
logger.debug("Providing notification for user %s", request.user)
|
||||||
context = {'notif': notif}
|
context = {'notif': notif}
|
||||||
notif.view()
|
notif.mark_viewed()
|
||||||
return render(request, 'notifications/view.html', context)
|
return render(request, 'notifications/view.html', context)
|
||||||
else:
|
else:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"User %s not authorized to view notif_id %s belonging to user %s" % (request.user, notif_id, notif.user))
|
"User %s not authorized to view notif_id %s belonging to user %s",
|
||||||
|
request.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.'))
|
||||||
return redirect('notifications:list')
|
return redirect('notifications:list')
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def remove_notification(request, notif_id):
|
def remove_notification(request, notif_id):
|
||||||
logger.debug("remove notification called by user %s for notif_id %s" % (request.user, notif_id))
|
logger.debug(
|
||||||
|
"remove notification called by user %s for notif_id %s",
|
||||||
|
request.user,
|
||||||
|
notif_id
|
||||||
|
)
|
||||||
notif = get_object_or_404(Notification, pk=notif_id)
|
notif = get_object_or_404(Notification, pk=notif_id)
|
||||||
if notif.user == request.user:
|
if notif.user == request.user:
|
||||||
if Notification.objects.filter(id=notif_id).exists():
|
if Notification.objects.filter(id=notif_id).exists():
|
||||||
notif.delete()
|
notif.delete()
|
||||||
logger.info("Deleting notif id %s by user %s" % (notif_id, request.user))
|
logger.info("Deleting notif id %s by user %s", notif_id, request.user)
|
||||||
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." % (notif_id, request.user))
|
"Unable to delete notif id %s for user %s - notif matching id not found.",
|
||||||
|
notif_id,
|
||||||
|
request.user
|
||||||
|
)
|
||||||
messages.error(request, _('Failed to locate notification.'))
|
messages.error(request, _('Failed to locate notification.'))
|
||||||
return redirect('notifications:list')
|
return redirect('notifications:list')
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def mark_all_read(request):
|
def mark_all_read(request):
|
||||||
logger.debug('mark all notifications read called by user %s' % request.user)
|
logger.debug('mark all notifications read called by user %s', request.user)
|
||||||
Notification.objects.filter(user=request.user).update(viewed=True)
|
Notification.objects.filter(user=request.user).update(viewed=True)
|
||||||
messages.success(request, _('Marked all notifications as read.'))
|
messages.success(request, _('Marked all notifications as read.'))
|
||||||
return redirect('notifications:list')
|
return redirect('notifications:list')
|
||||||
@@ -63,7 +86,17 @@ def mark_all_read(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def delete_all_read(request):
|
def delete_all_read(request):
|
||||||
logger.debug('delete all read notifications called by user %s' % request.user)
|
logger.debug('delete all read notifications called by user %s', request.user)
|
||||||
Notification.objects.filter(user=request.user).filter(viewed=True).delete()
|
Notification.objects.filter(user=request.user).filter(viewed=True).delete()
|
||||||
messages.success(request, _('Deleted all read notifications.'))
|
messages.success(request, _('Deleted all read notifications.'))
|
||||||
return redirect('notifications:list')
|
return redirect('notifications:list')
|
||||||
|
|
||||||
|
|
||||||
|
def user_notifications_count(request, user_pk: int):
|
||||||
|
"""returns to notifications count for the give user as JSON
|
||||||
|
|
||||||
|
This view is public and does not require login
|
||||||
|
"""
|
||||||
|
unread_count = Notification.objects.user_unread_count(user_pk)
|
||||||
|
data = {'unread_count': unread_count}
|
||||||
|
return JsonResponse(data, safe=False)
|
||||||
|
|||||||
@@ -104,8 +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.notifications.context_processors.user_notification_count',
|
|
||||||
'allianceauth.context_processors.auth_settings',
|
'allianceauth.context_processors.auth_settings',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -173,6 +172,8 @@ CACHES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
|
|||||||
@@ -83,10 +83,31 @@ class DiscordUserManager(models.Manager):
|
|||||||
if created is not False:
|
if created is not False:
|
||||||
if created is None:
|
if created is None:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"User %s with Discord ID %s is already a member.",
|
"User %s with Discord ID %s is already a member. Forcing a Refresh",
|
||||||
user,
|
user,
|
||||||
user_id,
|
user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Force an update cause the discord API won't do it for us.
|
||||||
|
if role_ids:
|
||||||
|
role_ids = list(role_ids)
|
||||||
|
|
||||||
|
updated = bot_client.modify_guild_member(
|
||||||
|
guild_id=DISCORD_GUILD_ID,
|
||||||
|
user_id=user_id,
|
||||||
|
role_ids=role_ids,
|
||||||
|
nick=nickname
|
||||||
|
)
|
||||||
|
|
||||||
|
if not updated:
|
||||||
|
# Could not update the new user so fail.
|
||||||
|
logger.warning(
|
||||||
|
"Failed to add user %s with Discord ID %s to Discord server",
|
||||||
|
user,
|
||||||
|
user_id,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
self.update_or_create(
|
self.update_or_create(
|
||||||
user=user,
|
user=user,
|
||||||
defaults={
|
defaults={
|
||||||
|
|||||||
@@ -111,6 +111,40 @@ class TestAddUser(TestCase):
|
|||||||
self.assertSetEqual(set(kwargs['role_ids']), {1, 2, 3})
|
self.assertSetEqual(set(kwargs['role_ids']), {1, 2, 3})
|
||||||
self.assertIsNone(kwargs['nick'])
|
self.assertIsNone(kwargs['nick'])
|
||||||
|
|
||||||
|
def test_can_activate_existing_user_with_roles_no_nick(
|
||||||
|
self,
|
||||||
|
mock_user_formatted_nick,
|
||||||
|
mock_user_group_names,
|
||||||
|
mock_exchange_auth_code_for_token,
|
||||||
|
mock_DiscordClient
|
||||||
|
):
|
||||||
|
roles = [
|
||||||
|
create_matched_role(ROLE_ALPHA),
|
||||||
|
create_matched_role(ROLE_BRAVO),
|
||||||
|
create_matched_role(ROLE_CHARLIE)
|
||||||
|
]
|
||||||
|
mock_user_formatted_nick.return_value = None
|
||||||
|
mock_user_group_names.return_value = ['a', 'b', 'c']
|
||||||
|
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.match_or_create_roles_from_names\
|
||||||
|
.return_value = roles
|
||||||
|
mock_DiscordClient.return_value.add_guild_member.return_value = None
|
||||||
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
|
self.assertTrue(result)
|
||||||
|
self.assertTrue(
|
||||||
|
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.modify_guild_member.called)
|
||||||
|
args, kwargs = mock_DiscordClient.return_value.modify_guild_member.call_args
|
||||||
|
self.assertEqual(kwargs['guild_id'], TEST_GUILD_ID)
|
||||||
|
self.assertEqual(kwargs['user_id'], TEST_USER_ID)
|
||||||
|
self.assertSetEqual(set(kwargs['role_ids']), {1, 2, 3})
|
||||||
|
self.assertIsNone(kwargs['nick'])
|
||||||
|
|
||||||
@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,
|
||||||
@@ -140,6 +174,36 @@ class TestAddUser(TestCase):
|
|||||||
self.assertIsNone(kwargs['role_ids'])
|
self.assertIsNone(kwargs['role_ids'])
|
||||||
self.assertEqual(kwargs['nick'], TEST_MAIN_NAME)
|
self.assertEqual(kwargs['nick'], TEST_MAIN_NAME)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.managers.DISCORD_SYNC_NAMES', True)
|
||||||
|
def test_can_activate_existing_user_no_roles_with_nick(
|
||||||
|
self,
|
||||||
|
mock_user_formatted_nick,
|
||||||
|
mock_user_group_names,
|
||||||
|
mock_exchange_auth_code_for_token,
|
||||||
|
mock_DiscordClient
|
||||||
|
):
|
||||||
|
mock_user_formatted_nick.return_value = TEST_MAIN_NAME
|
||||||
|
mock_user_group_names.return_value = []
|
||||||
|
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.match_or_create_roles_from_names\
|
||||||
|
.return_value = []
|
||||||
|
mock_DiscordClient.return_value.add_guild_member.return_value = None
|
||||||
|
mock_DiscordClient.return_value.modify_guild_member.return_value = True
|
||||||
|
|
||||||
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
|
self.assertTrue(result)
|
||||||
|
self.assertTrue(
|
||||||
|
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.modify_guild_member.called)
|
||||||
|
args, kwargs = mock_DiscordClient.return_value.modify_guild_member.call_args
|
||||||
|
self.assertEqual(kwargs['guild_id'], TEST_GUILD_ID)
|
||||||
|
self.assertEqual(kwargs['user_id'], TEST_USER_ID)
|
||||||
|
self.assertIsNone(kwargs['role_ids'])
|
||||||
|
self.assertEqual(kwargs['nick'], TEST_MAIN_NAME)
|
||||||
|
|
||||||
@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,
|
||||||
@@ -183,6 +247,7 @@ class TestAddUser(TestCase):
|
|||||||
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
|
||||||
|
mock_DiscordClient.return_value.modify_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)
|
||||||
@@ -190,6 +255,31 @@ class TestAddUser(TestCase):
|
|||||||
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)
|
||||||
|
self.assertTrue(mock_DiscordClient.return_value.modify_guild_member.called)
|
||||||
|
|
||||||
|
def test_can_activate_existing_guild_member_failure(
|
||||||
|
self,
|
||||||
|
mock_user_formatted_nick,
|
||||||
|
mock_user_group_names,
|
||||||
|
mock_exchange_auth_code_for_token,
|
||||||
|
mock_DiscordClient
|
||||||
|
):
|
||||||
|
mock_user_formatted_nick.return_value = None
|
||||||
|
mock_user_group_names.return_value = []
|
||||||
|
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.match_or_create_roles_from_names\
|
||||||
|
.return_value = []
|
||||||
|
mock_DiscordClient.return_value.add_guild_member.return_value = None
|
||||||
|
mock_DiscordClient.return_value.modify_guild_member.return_value = False
|
||||||
|
|
||||||
|
result = DiscordUser.objects.add_user(self.user, authorization_code='abcdef')
|
||||||
|
self.assertFalse(result)
|
||||||
|
self.assertFalse(
|
||||||
|
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.modify_guild_member.called)
|
||||||
|
|
||||||
def test_return_false_when_user_creation_fails(
|
def test_return_false_when_user_creation_fails(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Generated by Django 3.1.2 on 2021-01-08 13:54
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.migrations.operations.special
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [('mumble', '0001_initial'), ('mumble', '0002_auto_20161212_0100'), ('mumble', '0003_mumbleuser_user'), ('mumble', '0004_auto_20161214_1024'), ('mumble', '0005_mumbleuser_hashfn'), ('mumble', '0006_service_permissions'), ('mumble', '0007_not_null_user'), ('mumble', '0008_mumbleuser_display_name'), ('mumble', '0009_set_mumble_dissplay_names'), ('mumble', '0010_mumbleuser_certhash'), ('mumble', '0011_auto_20201011_1009')]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MumbleUser',
|
||||||
|
fields=[
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='mumble', serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('username', models.CharField(max_length=254, unique=True)),
|
||||||
|
('pwhash', models.CharField(max_length=40)),
|
||||||
|
('groups', models.TextField(blank=True, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'services_mumbleuser',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterModelTable(
|
||||||
|
name='mumbleuser',
|
||||||
|
table=None,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='hashfn',
|
||||||
|
field=models.CharField(default='sha1', max_length=20),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='pwhash',
|
||||||
|
field=models.CharField(max_length=80),
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='mumbleuser',
|
||||||
|
options={'permissions': (('access_mumble', 'Can access the Mumble service'),)},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='display_name',
|
||||||
|
field=models.CharField(max_length=254, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='display_name',
|
||||||
|
field=models.CharField(max_length=254, unique=True),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='certhash',
|
||||||
|
field=models.CharField(blank=True, editable=False, help_text='Hash of Mumble client certificate as presented when user authenticates', max_length=254, null=True, verbose_name='Certificate Hash'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='pwhash',
|
||||||
|
field=models.CharField(max_length=90),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 3.1.6 on 2021-03-23 13:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mumble', '0001_squashed_0011_auto_20201011_1009'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='last_connect',
|
||||||
|
field=models.DateTimeField(blank=True, editable=False, help_text='Timestamp of the users Last Connection to Mumble', max_length=254, null=True, verbose_name='Last Connection'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='last_disconnect',
|
||||||
|
field=models.DateTimeField(blank=True, editable=False, help_text='Timestamp of the users Last Disconnection to Mumble', max_length=254, null=True, verbose_name='Last Disconnection'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='release',
|
||||||
|
field=models.TextField(blank=True, editable=False, help_text='The Mumble Release the user last authenticated with', max_length=254, null=True, verbose_name='Mumble Release'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='version',
|
||||||
|
field=models.IntegerField(blank=True, editable=False, help_text='Client version. Major version in upper 16 bits, followed by 8 bits of minor version and 8 bits of patchlevel. Version 1.2.3 = 0x010203.', null=True, verbose_name='Mumble Version'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -74,7 +74,41 @@ class MumbleUser(AbstractServiceModel):
|
|||||||
editable=False,
|
editable=False,
|
||||||
help_text="Hash of Mumble client certificate as presented when user authenticates"
|
help_text="Hash of Mumble client certificate as presented when user authenticates"
|
||||||
)
|
)
|
||||||
display_name = models.CharField(max_length=254, unique=True)
|
display_name = models.CharField(
|
||||||
|
max_length=254,
|
||||||
|
unique=True
|
||||||
|
)
|
||||||
|
release = models.TextField(
|
||||||
|
verbose_name="Mumble Release",
|
||||||
|
max_length=254,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="The Mumble Release the user last authenticated with"
|
||||||
|
)
|
||||||
|
version = models.IntegerField(
|
||||||
|
verbose_name="Mumble Version",
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="Client version. Major version in upper 16 bits, followed by 8 bits of minor version and 8 bits of patchlevel. Version 1.2.3 = 0x010203."
|
||||||
|
)
|
||||||
|
last_connect = models.DateTimeField(
|
||||||
|
verbose_name="Last Connection",
|
||||||
|
max_length=254,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="Timestamp of the users Last Connection to Mumble"
|
||||||
|
)
|
||||||
|
last_disconnect = models.DateTimeField(
|
||||||
|
verbose_name="Last Disconnection",
|
||||||
|
max_length=254,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="Timestamp of the users Last Disconnection to Mumble"
|
||||||
|
)
|
||||||
|
|
||||||
objects = MumbleManager()
|
objects = MumbleManager()
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class Teamspeak3UserAdmin(ServicesUserAdmin):
|
|||||||
|
|
||||||
@admin.register(AuthTS)
|
@admin.register(AuthTS)
|
||||||
class AuthTSgroupAdmin(admin.ModelAdmin):
|
class AuthTSgroupAdmin(admin.ModelAdmin):
|
||||||
|
change_list_template = 'admin/teamspeak3/authts/change_list.html'
|
||||||
ordering = ('auth_group__name', )
|
ordering = ('auth_group__name', )
|
||||||
list_select_related = True
|
list_select_related = True
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ class AuthTSgroupAdmin(admin.ModelAdmin):
|
|||||||
return [x for x in obj.ts_group.all().order_by('ts_group_id')]
|
return [x for x in obj.ts_group.all().order_by('ts_group_id')]
|
||||||
|
|
||||||
_ts_group.short_description = 'ts groups'
|
_ts_group.short_description = 'ts groups'
|
||||||
#_ts_group.admin_order_field = 'profile__state'
|
# _ts_group.admin_order_field = 'profile__state'
|
||||||
|
|
||||||
|
|
||||||
@admin.register(StateGroup)
|
@admin.register(StateGroup)
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{% extends "admin/change_list.html" %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block object-tools-items %}
|
||||||
|
{{ block.super }}
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'teamspeak3:admin_update_ts3_groups' %}" class="btn btn-high">
|
||||||
|
Update TS3 groups
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endblock %}
|
||||||
@@ -216,6 +216,24 @@ class Teamspeak3ViewsTestCase(TestCase):
|
|||||||
self.assertEqual(ts3_user.perm_key, '123abc')
|
self.assertEqual(ts3_user.perm_key, '123abc')
|
||||||
self.assertTrue(tasks_manager.return_value.__enter__.return_value.update_groups.called)
|
self.assertTrue(tasks_manager.return_value.__enter__.return_value.update_groups.called)
|
||||||
|
|
||||||
|
@mock.patch(MODULE_PATH + '.views.Teamspeak3Tasks')
|
||||||
|
@mock.patch(MODULE_PATH + '.views.messages')
|
||||||
|
def test_should_update_ts_groups(self, messages, Teamspeak3Tasks):
|
||||||
|
# given
|
||||||
|
self.member.is_superuser = True
|
||||||
|
self.member.is_staff = True
|
||||||
|
self.member.save()
|
||||||
|
self.login()
|
||||||
|
# when
|
||||||
|
response = self.client.get(urls.reverse('teamspeak3:admin_update_ts3_groups'))
|
||||||
|
# then
|
||||||
|
self.assertRedirects(
|
||||||
|
response, urls.reverse('admin:teamspeak3_authts_changelist'),
|
||||||
|
target_status_code=200
|
||||||
|
)
|
||||||
|
self.assertTrue(messages.info.called)
|
||||||
|
self.assertTrue(Teamspeak3Tasks.run_ts3_group_update.delay.called)
|
||||||
|
|
||||||
|
|
||||||
class Teamspeak3SignalsTestCase(TestCase):
|
class Teamspeak3SignalsTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ app_name = 'teamspeak3'
|
|||||||
|
|
||||||
module_urls = [
|
module_urls = [
|
||||||
# Teamspeak3 service control
|
# Teamspeak3 service control
|
||||||
url(r'^activate/$', views.activate_teamspeak3,
|
url(r'^activate/$', views.activate_teamspeak3, name='activate'),
|
||||||
name='activate'),
|
url(r'^deactivate/$', views.deactivate_teamspeak3, name='deactivate'),
|
||||||
url(r'^deactivate/$', views.deactivate_teamspeak3,
|
url(r'^reset_perm/$', views.reset_teamspeak3_perm, name='reset_perm'),
|
||||||
name='deactivate'),
|
url(
|
||||||
url(r'^reset_perm/$', views.reset_teamspeak3_perm,
|
r'^admin_update_ts3_groups/$',
|
||||||
name='reset_perm'),
|
views.admin_update_ts3_groups,
|
||||||
|
name='admin_update_ts3_groups'
|
||||||
|
),
|
||||||
|
|
||||||
# Teamspeak Urls
|
# Teamspeak Urls
|
||||||
url(r'^verify/$', views.verify_teamspeak3, name='verify'),
|
url(r'^verify/$', views.verify_teamspeak3, name='verify'),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
from django.contrib.auth.decorators import login_required, permission_required
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -99,3 +100,11 @@ def reset_teamspeak3_perm(request):
|
|||||||
logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user)
|
logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user)
|
||||||
messages.error(request, _('An error occurred while processing your TeamSpeak3 account.'))
|
messages.error(request, _('An error occurred while processing your TeamSpeak3 account.'))
|
||||||
return redirect("services:services")
|
return redirect("services:services")
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@staff_member_required
|
||||||
|
def admin_update_ts3_groups(request):
|
||||||
|
Teamspeak3Tasks.run_ts3_group_update.delay()
|
||||||
|
messages.info(request, "Started updating TS3 server groups...")
|
||||||
|
return redirect("admin:teamspeak3_authts_changelist")
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
@@ -21,6 +23,11 @@ class SrpFleetUserRequestForm(forms.Form):
|
|||||||
data = self.cleaned_data['killboard_link']
|
data = self.cleaned_data['killboard_link']
|
||||||
if "zkillboard.com" not in data:
|
if "zkillboard.com" not in data:
|
||||||
raise forms.ValidationError(_("Invalid Link. Please use zKillboard.com"))
|
raise forms.ValidationError(_("Invalid Link. Please use zKillboard.com"))
|
||||||
|
|
||||||
|
if not re.match(r"http[s]?://zkillboard\.com/kill/\d+\/", data):
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_("Invalid Link. Please post a direct link to a killmail.")
|
||||||
|
)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
{% include 'bundles/x-editable.css.html' %}
|
{% include 'bundles/x-editable.css.html' %}
|
||||||
<link href="{% static 'css/checkbox.css' %}" rel="stylesheet" type="text/css">
|
<link href="{% static 'css/checkbox.css' %}" rel="stylesheet" type="text/css">
|
||||||
<style>
|
<style>
|
||||||
|
.copy-text-fa-icon:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
.radio label, .checkbox label {
|
.radio label, .checkbox label {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
@@ -109,7 +112,8 @@ ESC to cancel{% endblocktrans %}"id="blah"></i></th>
|
|||||||
{{ srpfleetrequest.character.alliance.alliance_ticker }}
|
{{ srpfleetrequest.character.alliance.alliance_ticker }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
[{{ srpfleetrequest.character.corporation.corporation_ticker }}]
|
[{{ srpfleetrequest.character.corporation.corporation_ticker }}]
|
||||||
{{ srpfleetrequest.character.character_name }}
|
{{ srpfleetrequest.character.character_name }} <i class="copy-text-fa-icon far fa-copy" data-clipboard-text="{{ srpfleetrequest.character.character_name }}"></i>
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="{{ srpfleetrequest.killboard_link }}"
|
<a href="{{ srpfleetrequest.killboard_link }}"
|
||||||
@@ -182,7 +186,24 @@ ESC to cancel{% endblocktrans %}"id="blah"></i></th>
|
|||||||
{% include 'bundles/datatables-js.html' %}
|
{% include 'bundles/datatables-js.html' %}
|
||||||
{% include 'bundles/x-editable-js.html' %}
|
{% include 'bundles/x-editable-js.html' %}
|
||||||
{% include 'bundles/moment-js.html' %}
|
{% include 'bundles/moment-js.html' %}
|
||||||
{% endblock %}
|
{% include 'bundles/clipboard-js.html' %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var clipboard = new ClipboardJS('.copy-text-fa-icon');
|
||||||
|
clipboard.on('success', function (e) {
|
||||||
|
console.info('Action:', e.action);
|
||||||
|
console.info('Text:', e.text);
|
||||||
|
console.info('Trigger:', e.trigger);
|
||||||
|
|
||||||
|
e.clearSelection();
|
||||||
|
});
|
||||||
|
|
||||||
|
clipboard.on('error', function (e) {
|
||||||
|
console.error('Action:', e.action);
|
||||||
|
console.error('Trigger:', e.trigger);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock extra_javascript %}
|
||||||
|
|
||||||
{% block extra_script %}
|
{% block extra_script %}
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|||||||
@@ -43,27 +43,51 @@ ul.list-group.list-group-horizontal > li.list-group-item {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* style group headers within a table */
|
@media all {
|
||||||
.tr-group {
|
/* style nav tabs in dark mode*/
|
||||||
font-weight: bold;
|
.template-dark-mode .nav-tabs > li.active > a {
|
||||||
background-color: #e6e6e6 !important;
|
background-color: rgb(70, 69, 69)!important;
|
||||||
}
|
color: rgb(255, 255, 255) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* default style for tables */
|
.panel-tabs-aa {
|
||||||
.table-aa > thead > tr > th{
|
border-top: none;
|
||||||
border-bottom: 1px solid #f2f2f2;
|
border-top-left-radius: 0%;
|
||||||
}
|
border-top-right-radius: 0%;
|
||||||
.table-aa > thead > tr > th{
|
}
|
||||||
vertical-align: middle;
|
|
||||||
}
|
/* style group headers within a table */
|
||||||
.table-aa > tbody > tr > td{
|
.template-light-mode .tr-group {
|
||||||
border-bottom: 1px solid #f2f2f2;
|
font-weight: bold;
|
||||||
}
|
background-color: #e6e6e6 !important;
|
||||||
.table-aa > tbody > tr > td {
|
}
|
||||||
vertical-align: middle;
|
.template-dark-mode .tr-group {
|
||||||
}
|
font-weight: bold;
|
||||||
.table-aa > tbody > tr:last-child {
|
background-color: rgb(105, 105, 105) !important;
|
||||||
border-bottom: none;
|
}
|
||||||
|
|
||||||
|
/* default style for tables */
|
||||||
|
.template-light-mode .table-aa > thead > tr > th{
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
}
|
||||||
|
.template-dark-mode .table-aa > thead > tr > th{
|
||||||
|
border-bottom: 1px solid rgb(70, 69, 69);
|
||||||
|
}
|
||||||
|
.table-aa > thead > tr > th{
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.template-light-mode .table-aa > tbody > tr > td{
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
}
|
||||||
|
.template-dark-mode .table-aa > tbody > tr > td{
|
||||||
|
border-bottom: 1px solid rgb(70, 69, 69);
|
||||||
|
}
|
||||||
|
.table-aa > tbody > tr > td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.table-aa > tbody > tr:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* highlight active menu items
|
/* highlight active menu items
|
||||||
|
|||||||
75
allianceauth/static/js/refresh_notifications.js
Normal file
75
allianceauth/static/js/refresh_notifications.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
This script refreshed the unread notification count in the top menu
|
||||||
|
on a regular basis so to keep the user apprised about newly arrived
|
||||||
|
notifications without having to reload the page.
|
||||||
|
|
||||||
|
The refresh rate can be changes via the Django setting NOTIFICATIONS_REFRESH_TIME.
|
||||||
|
See documentation for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
var elem = document.getElementById("dataExport");
|
||||||
|
var notificationsListViewUrl = elem.getAttribute("data-notificationsListViewUrl");
|
||||||
|
var notificationsRefreshTime = elem.getAttribute("data-notificationsRefreshTime");
|
||||||
|
var userNotificationsCountViewUrl = elem.getAttribute(
|
||||||
|
"data-userNotificationsCountViewUrl"
|
||||||
|
);
|
||||||
|
|
||||||
|
// update the notification unread count in the top menu
|
||||||
|
function update_notifications() {
|
||||||
|
$.getJSON(userNotificationsCountViewUrl, function (data, status) {
|
||||||
|
if (status == 'success') {
|
||||||
|
var innerHtml = "";
|
||||||
|
var unread_count = data.unread_count;
|
||||||
|
if (unread_count > 0) {
|
||||||
|
innerHtml = (
|
||||||
|
`Notifications <span class="badge">${unread_count}</span>`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
innerHtml = '<i class="far fa-bell"></i>'
|
||||||
|
}
|
||||||
|
$("#menu_item_notifications").html(
|
||||||
|
`<a href="${notificationsListViewUrl}">${innerHtml}</a>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error(
|
||||||
|
`Failed to load HTMl to render notifications item. Error: `
|
||||||
|
`${xhr.status}': '${xhr.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var myInterval;
|
||||||
|
|
||||||
|
// activate automatic refreshing every x seconds
|
||||||
|
function activate_refreshing() {
|
||||||
|
if (notificationsRefreshTime > 0) {
|
||||||
|
myInterval = setInterval(
|
||||||
|
update_notifications, notificationsRefreshTime * 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deactivate automatic refreshing
|
||||||
|
function deactivate_refreshing() {
|
||||||
|
if ((notificationsRefreshTime > 0) && (typeof myInterval !== 'undefined')) {
|
||||||
|
clearInterval(myInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// refreshing only happens on active browser tab
|
||||||
|
$(document).on({
|
||||||
|
'show': function () {
|
||||||
|
activate_refreshing()
|
||||||
|
},
|
||||||
|
'hide': function () {
|
||||||
|
deactivate_refreshing()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial start of refreshing on script loading
|
||||||
|
activate_refreshing()
|
||||||
|
});
|
||||||
@@ -18,9 +18,20 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right" style="position:absolute;bottom:5px;right:5px;">
|
|
||||||
<a href="https://gitlab.com/allianceauth/allianceauth/issues"><span class="label" style="background-color:#e65328;">
|
<div class="text-right" style="position: absolute; bottom: 5px; right: 5px;">
|
||||||
<i class="fab fa-gitlab" aria-hidden="true"></i> Powered by GitLab</span>
|
<a href="https://gitlab.com/allianceauth/allianceauth/issues" target="_blank" style="margin-right: 0.5rem;">
|
||||||
|
<span class="label" style="background-color: #e65328;">
|
||||||
|
<i class="fab fa-gitlab" aria-hidden="true"></i>
|
||||||
|
{% translate 'Powered by GitLab' %}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://discord.com/invite/fjnHAmk" target="_blank">
|
||||||
|
<span class="label" style="background-color: rgb(110,133,211);">
|
||||||
|
<i class="fab fa-discord" aria-hidden="true"></i>
|
||||||
|
{% translate 'Support Discord' %}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load navactive %}
|
{% load navactive %}
|
||||||
|
{% load auth_notifications %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -9,7 +10,6 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
|
|
||||||
{% include 'allianceauth/icons.html' %}
|
{% include 'allianceauth/icons.html' %}
|
||||||
|
|
||||||
<title>{% block title %}{% block page_title %}{% endblock page_title %} - Alliance Auth{% endblock title %}</title>
|
<title>{% block title %}{% block page_title %}{% endblock page_title %} - Alliance Auth{% endblock title %}</title>
|
||||||
@@ -27,20 +27,10 @@
|
|||||||
<div id="wrapper" class="container">
|
<div id="wrapper" class="container">
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
{% include 'allianceauth/top-menu.html' %}
|
{% include 'allianceauth/top-menu.html' %}
|
||||||
|
|
||||||
<div class="row" id="site-body-wrapper">
|
<div class="row" id="site-body-wrapper">
|
||||||
{% include 'allianceauth/side-menu.html' %}
|
{% include 'allianceauth/side-menu.html' %}
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
{% if messages %}
|
{% include 'allianceauth/messages.html' %}
|
||||||
<br>
|
|
||||||
{% for message in messages %}
|
|
||||||
<div class="alert alert-{{ message.level_tag }}">{{ message }}</div>
|
|
||||||
{% if not forloop.last %}
|
|
||||||
<br>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
</div>
|
</div>
|
||||||
@@ -48,12 +38,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<!-- share data with JS part -->
|
||||||
|
<div
|
||||||
|
id="dataExport"
|
||||||
|
data-notificationsListViewUrl="{% url 'notifications:list' %}"
|
||||||
|
data-notificationsRefreshTime="{% notifications_refresh_time %}"
|
||||||
|
data-userNotificationsCountViewUrl="{% url 'notifications:user_notifications_count' request.user.pk %}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
{% include 'bundles/bootstrap-js.html' %}
|
{% include 'bundles/bootstrap-js.html' %}
|
||||||
|
{% include 'bundles/jquery-visibility-js.html' %}
|
||||||
{% block extra_javascript %}
|
<script src="{% static 'js/refresh_notifications.js' %}"></script>
|
||||||
|
|
||||||
|
{% block extra_javascript %}
|
||||||
{% endblock extra_javascript %}
|
{% endblock extra_javascript %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
{% block extra_script %}
|
{% block extra_script %}
|
||||||
{% endblock extra_script %}
|
{% endblock extra_script %}
|
||||||
|
|||||||
26
allianceauth/templates/allianceauth/messages.html
Normal file
26
allianceauth/templates/allianceauth/messages.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{% if messages %}
|
||||||
|
<br>
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="alert alert-{{ message.level_tag }} alert-dismissible" role="alert">
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="message-icon pull-left" style="margin-right: 0.5rem;">
|
||||||
|
{% if message.level_tag == "info" %}
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
{% elif message.level_tag == "success" %}
|
||||||
|
<i class="fas fa-check-circle"></i>
|
||||||
|
{% elif message.level_tag == "warning" %}
|
||||||
|
<i class="fas fa-exclamation-circle"></i>
|
||||||
|
{% elif message.level_tag == "danger" %}
|
||||||
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="message-text" style="margin-left: 2.5rem;">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{% load auth_notifications %}
|
||||||
|
|
||||||
|
{% with unread_count=request.user|user_unread_notification_count %}
|
||||||
|
{% if unread_count > 0 %}
|
||||||
|
<a href="{% url 'notifications:list' %}">Notifications
|
||||||
|
<span class="badge">{{ unread_count }}</span>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'notifications:list' %}">
|
||||||
|
<i class="far fa-bell"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
@@ -20,17 +20,11 @@
|
|||||||
<li>
|
<li>
|
||||||
{% include 'allianceauth/night-toggle.html' %}
|
{% include 'allianceauth/night-toggle.html' %}
|
||||||
</li>
|
</li>
|
||||||
{% if notifications %}
|
<li
|
||||||
<li class="{% navactive request 'notifications:' %}">
|
class="{% navactive request 'notifications:' %}" id="menu_item_notifications"
|
||||||
<a href="{% url 'notifications:list' %}">Notifications
|
>
|
||||||
<span class="badge">{{ notifications }}</span>
|
{% include 'allianceauth/notifications_menu_item.html' %}
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
|
||||||
<li><a href="{% url 'notifications:list' %}">
|
|
||||||
<i class="far fa-bell"></i></a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
{% if user.is_staff %}
|
{% if user.is_staff %}
|
||||||
<li><a href="{% url 'admin:index' %}">{% trans "Admin" %}</a></li>
|
<li><a href="{% url 'admin:index' %}">{% trans "Admin" %}</a></li>
|
||||||
@@ -64,3 +58,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<!-- Start Clipboard.js js from cdnjs -->
|
<!-- Start Clipboard.js js from cdnjs -->
|
||||||
<script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.6/clipboard.min.js"></script>
|
<script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.8/clipboard.min.js" integrity="sha512-sIqUEnRn31BgngPmHt2JenzleDDsXwYO+iyvQ46Mw6RL+udAUZj2n/u/PGY80NxRxynO7R9xIGx5LEzw4INWJQ==" crossorigin="anonymous"></script>
|
||||||
<!-- End Clipboard.js js from cdnjs -->
|
<!-- End Clipboard.js js from cdnjs -->
|
||||||
4
allianceauth/templates/bundles/jquery-visibility-js.html
Normal file
4
allianceauth/templates/bundles/jquery-visibility-js.html
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{% load static %}
|
||||||
|
<!-- Start jQuery visibility js -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-visibility/1.0.11/jquery-visibility.min.js"></script>
|
||||||
|
<!-- End jQuery visibility js -->
|
||||||
@@ -27,7 +27,7 @@ GITLAB_AUTH_REPOSITORY_TAGS_URL = (
|
|||||||
)
|
)
|
||||||
GITLAB_AUTH_ANNOUNCEMENT_ISSUES_URL = (
|
GITLAB_AUTH_ANNOUNCEMENT_ISSUES_URL = (
|
||||||
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
'https://gitlab.com/api/v4/projects/allianceauth%2Fallianceauth/issues'
|
||||||
'?labels=announcement'
|
'?labels=announcement&state=opened'
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
|
|||||||
@register.inclusion_tag('allianceauth/admin-status/overview.html')
|
@register.inclusion_tag('allianceauth/admin-status/overview.html')
|
||||||
def status_overview() -> dict:
|
def status_overview() -> dict:
|
||||||
response = {
|
response = {
|
||||||
'notifications': list(),
|
'notifications': list(),
|
||||||
'current_version': __version__,
|
'current_version': __version__,
|
||||||
'task_queue_length': -1,
|
'task_queue_length': -1,
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ def _fetch_celery_queue_length() -> int:
|
|||||||
app = app_or_default(None)
|
app = app_or_default(None)
|
||||||
with app.connection_or_acquire() as conn:
|
with app.connection_or_acquire() as conn:
|
||||||
return conn.default_channel.queue_declare(
|
return conn.default_channel.queue_declare(
|
||||||
queue=getattr(settings, 'CELERY_DEFAULT_QUEUE', 'celery'),
|
queue=getattr(settings, 'CELERY_DEFAULT_QUEUE', 'celery'),
|
||||||
passive=True
|
passive=True
|
||||||
).message_count
|
).message_count
|
||||||
except amqp.exceptions.ChannelError:
|
except amqp.exceptions.ChannelError:
|
||||||
@@ -63,51 +63,51 @@ def _fetch_celery_queue_length() -> int:
|
|||||||
|
|
||||||
|
|
||||||
def _current_notifications() -> dict:
|
def _current_notifications() -> dict:
|
||||||
"""returns the newest 5 announcement issues"""
|
"""returns the newest 5 announcement issues"""
|
||||||
try:
|
try:
|
||||||
notifications = cache.get_or_set(
|
notifications = cache.get_or_set(
|
||||||
'gitlab_notification_issues',
|
'gitlab_notification_issues',
|
||||||
_fetch_notification_issues_from_gitlab,
|
_fetch_notification_issues_from_gitlab,
|
||||||
NOTIFICATION_CACHE_TIME
|
NOTIFICATION_CACHE_TIME
|
||||||
)
|
)
|
||||||
except requests.RequestException:
|
except requests.HTTPError:
|
||||||
logger.exception('Error while getting gitlab notifications')
|
logger.warning('Error while getting gitlab notifications', exc_info=True)
|
||||||
top_notifications = []
|
top_notifications = []
|
||||||
else:
|
else:
|
||||||
if notifications:
|
if notifications:
|
||||||
top_notifications = notifications[:5]
|
top_notifications = notifications[:5]
|
||||||
else:
|
else:
|
||||||
top_notifications = []
|
top_notifications = []
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
'notifications': top_notifications,
|
'notifications': top_notifications,
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def _fetch_notification_issues_from_gitlab() -> list:
|
def _fetch_notification_issues_from_gitlab() -> list:
|
||||||
return _fetch_list_from_gitlab(GITLAB_AUTH_ANNOUNCEMENT_ISSUES_URL, max_pages=10)
|
return _fetch_list_from_gitlab(GITLAB_AUTH_ANNOUNCEMENT_ISSUES_URL, max_pages=10)
|
||||||
|
|
||||||
|
|
||||||
def _current_version_summary() -> dict:
|
def _current_version_summary() -> dict:
|
||||||
"""returns the current version info"""
|
"""returns the current version info"""
|
||||||
try:
|
try:
|
||||||
tags = cache.get_or_set(
|
tags = cache.get_or_set(
|
||||||
'git_release_tags', _fetch_tags_from_gitlab, TAG_CACHE_TIME
|
'git_release_tags', _fetch_tags_from_gitlab, TAG_CACHE_TIME
|
||||||
)
|
)
|
||||||
except requests.RequestException:
|
except requests.HTTPError:
|
||||||
logger.exception('Error while getting gitlab release tags')
|
logger.warning('Error while getting gitlab release tags', exc_info=True)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
if not tags:
|
if not tags:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
(
|
(
|
||||||
latest_major_version,
|
latest_major_version,
|
||||||
latest_minor_version,
|
latest_minor_version,
|
||||||
latest_patch_version,
|
latest_patch_version,
|
||||||
latest_beta_version
|
latest_beta_version
|
||||||
) = _latests_versions(tags)
|
) = _latests_versions(tags)
|
||||||
current_version = Pep440Version(__version__)
|
current_version = Pep440Version(__version__)
|
||||||
|
|
||||||
has_latest_major = \
|
has_latest_major = \
|
||||||
@@ -121,7 +121,7 @@ def _current_version_summary() -> dict:
|
|||||||
and latest_major_version.base_version <= latest_beta_version.base_version \
|
and latest_major_version.base_version <= latest_beta_version.base_version \
|
||||||
if latest_beta_version else False
|
if latest_beta_version else False
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
'latest_major': has_latest_major,
|
'latest_major': has_latest_major,
|
||||||
'latest_minor': has_latest_minor,
|
'latest_minor': has_latest_minor,
|
||||||
'latest_patch': has_latest_patch,
|
'latest_patch': has_latest_patch,
|
||||||
@@ -131,7 +131,7 @@ def _current_version_summary() -> dict:
|
|||||||
'latest_minor_version': str(latest_minor_version),
|
'latest_minor_version': str(latest_minor_version),
|
||||||
'latest_patch_version': str(latest_patch_version),
|
'latest_patch_version': str(latest_patch_version),
|
||||||
'latest_beta_version': str(latest_beta_version)
|
'latest_beta_version': str(latest_beta_version)
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@@ -141,14 +141,14 @@ def _fetch_tags_from_gitlab():
|
|||||||
|
|
||||||
def _latests_versions(tags: list) -> tuple:
|
def _latests_versions(tags: list) -> tuple:
|
||||||
"""returns latests version from given tags list
|
"""returns latests version from given tags list
|
||||||
|
|
||||||
Non-compliant tags will be ignored
|
Non-compliant tags will be ignored
|
||||||
"""
|
"""
|
||||||
versions = list()
|
versions = list()
|
||||||
betas = list()
|
betas = list()
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
try:
|
try:
|
||||||
version = Pep440Version(tag.get('name'))
|
version = Pep440Version(tag.get('name'))
|
||||||
except InvalidVersion:
|
except InvalidVersion:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@@ -162,21 +162,21 @@ def _latests_versions(tags: list) -> tuple:
|
|||||||
v for v in versions if v.major == latest_version.major
|
v for v in versions if v.major == latest_version.major
|
||||||
])
|
])
|
||||||
latest_minor_version = min([
|
latest_minor_version = min([
|
||||||
v for v in versions
|
v for v in versions
|
||||||
if v.major == latest_version.major and v.minor == latest_version.minor
|
if v.major == latest_version.major and v.minor == latest_version.minor
|
||||||
])
|
])
|
||||||
latest_beta_version = max(betas)
|
latest_beta_version = max(betas)
|
||||||
return (
|
return (
|
||||||
latest_major_version,
|
latest_major_version,
|
||||||
latest_minor_version,
|
latest_minor_version,
|
||||||
latest_patch_version,
|
latest_patch_version,
|
||||||
latest_beta_version
|
latest_beta_version
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _fetch_list_from_gitlab(url: str, max_pages: int = MAX_PAGES) -> list:
|
def _fetch_list_from_gitlab(url: str, max_pages: int = MAX_PAGES) -> list:
|
||||||
"""returns a list from the GitLab API. Supports pageing"""
|
"""returns a list from the GitLab API. Supports pageing"""
|
||||||
result = list()
|
result = list()
|
||||||
for page in range(1, max_pages + 1):
|
for page in range(1, max_pages + 1):
|
||||||
request = requests.get(
|
request = requests.get(
|
||||||
url, params={'page': page}, timeout=REQUESTS_TIMEOUT
|
url, params={'page': page}, timeout=REQUESTS_TIMEOUT
|
||||||
@@ -190,8 +190,8 @@ def _fetch_list_from_gitlab(url: str, max_pages: int = MAX_PAGES) -> list:
|
|||||||
total_pages = None
|
total_pages = None
|
||||||
else:
|
else:
|
||||||
total_pages = None
|
total_pages = None
|
||||||
|
|
||||||
if not total_pages or page >= total_pages:
|
if not total_pages or page >= total_pages:
|
||||||
break
|
break
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
BIN
docs/_static/images/features/core/notifications.png
vendored
Normal file
BIN
docs/_static/images/features/core/notifications.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -23,7 +23,7 @@ Within your auth project exists two folders named `static` and `templates`. Thes
|
|||||||
|
|
||||||
You can add extra static or templates by putting files in these folders. Note that changes to static requires running the `python manage.py collectstatic` command to copy to the web server directory.
|
You can add extra static or templates by putting files in these folders. Note that changes to static requires running the `python manage.py collectstatic` command to copy to the web server directory.
|
||||||
|
|
||||||
It is possible to overload static and templates shipped with Django or Alliance Auth by including a file with the exact path of the one you wish to overload. For instance if you wish to add extra links to the menu bar by editing the template, you would make a copy of the `allianceauth/templates/allianceauth/base.html` file to `myauth/templates/allinceauth/base.html` and edit it there. Notice the paths are identical after the `templates/` directory - this is critical for it to be recognized. Your custom template would be used instead of the one included with Alliance Auth when Django renders the web page. Similar idea for static: put CSS or images at an identical path after the `static/` directory and they will be copied to the web server directory instead of the ones included.
|
It is possible to overload static and templates shipped with Django or Alliance Auth by including a file with the exact path of the one you wish to overload. For instance if you wish to add extra links to the menu bar by editing the template, you would make a copy of the `allianceauth/templates/allianceauth/base.html` file to `myauth/templates/allianceauth/base.html` and edit it there. Notice the paths are identical after the `templates/` directory - this is critical for it to be recognized. Your custom template would be used instead of the one included with Alliance Auth when Django renders the web page. Similar idea for static: put CSS or images at an identical path after the `static/` directory and they will be copied to the web server directory instead of the ones included.
|
||||||
|
|
||||||
## Custom URLs and Views
|
## Custom URLs and Views
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ The development environment consists of the following components:
|
|||||||
|
|
||||||
We will use the build-in Django development webserver, so we don't need to setup a WSGI server or a web server.
|
We will use the build-in Django development webserver, so we don't need to setup a WSGI server or a web server.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
.. note::
|
||||||
|
This setup works with both WSL 1 and WSL 2. However, due to the significantly better performance we recommend WSL 2.
|
||||||
|
```
|
||||||
|
|
||||||
## Requirement
|
## Requirement
|
||||||
|
|
||||||
The only requirement is a PC with Windows 10 and Internet connection in order to download the additional software components.
|
The only requirement is a PC with Windows 10 and Internet connection in order to download the additional software components.
|
||||||
@@ -361,8 +366,7 @@ Here is an example debug config for Celery:
|
|||||||
"module": "celery",
|
"module": "celery",
|
||||||
"cwd": "${workspaceFolder}/myauth",
|
"cwd": "${workspaceFolder}/myauth",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"args": [
|
"args": [
|
||||||
"-E",
|
|
||||||
"-A",
|
"-A",
|
||||||
"myauth",
|
"myauth",
|
||||||
"worker",
|
"worker",
|
||||||
@@ -371,7 +375,8 @@ Here is an example debug config for Celery:
|
|||||||
"-P",
|
"-P",
|
||||||
"solo",
|
"solo",
|
||||||
],
|
],
|
||||||
"django": true
|
"django": true,
|
||||||
|
"justMyCode": true,
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -386,15 +391,14 @@ Finally it makes sense to have a dedicated debug config for running unit tests.
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/myauth/manage.py",
|
"program": "${workspaceFolder}/myauth/manage.py",
|
||||||
"args": [
|
"args": [
|
||||||
"test",
|
"test",
|
||||||
"-v 2",
|
|
||||||
"--keepdb",
|
"--keepdb",
|
||||||
"--debug-mode",
|
"--debug-mode",
|
||||||
"--failfast",
|
"--failfast",
|
||||||
"example",
|
"example",
|
||||||
],
|
],
|
||||||
|
"django": true,
|
||||||
"django": true
|
"justMyCode": true
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -416,13 +420,31 @@ Finally you may also want to have a debug config to debug a non-Django Python sc
|
|||||||
|
|
||||||
## Additional tools
|
## Additional tools
|
||||||
|
|
||||||
The following additional tools are very helpful when developing for AA.
|
The following additional tools are very helpful when developing for AA with VS Code:
|
||||||
|
|
||||||
|
### Pylance
|
||||||
|
|
||||||
|
Pylance is an extension that works alongside Python in Visual Studio Code to provide performant language support: [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance)
|
||||||
|
|
||||||
### Code Spell Checker
|
### Code Spell Checker
|
||||||
|
|
||||||
Typos in your user facing comments can be quite embarrassing. This spell checker helps you avoid them.
|
Typos in your user facing comments can be quite embarrassing. This spell checker helps you avoid them: [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
|
||||||
|
|
||||||
Install from here: [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
|
### markdownlint
|
||||||
|
|
||||||
|
Extension for Visual Studio Code - Markdown linting and style checking for Visual Studio Code: [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
|
||||||
|
|
||||||
|
### GitLens
|
||||||
|
|
||||||
|
Extension for Visual Studio Code - Supercharge the Git capabilities built into Visual Studio Code: [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||||
|
|
||||||
|
### RST preview
|
||||||
|
|
||||||
|
A VS Code extension to preview restructured text and provide syntax highlighting: [RST Preview](https://marketplace.visualstudio.com/items?itemName=tht13.rst-vscode)
|
||||||
|
|
||||||
|
### Django Template
|
||||||
|
|
||||||
|
This extension adds language colorization support and user snippets for the Django template language to VS Code: [Django Template](https://marketplace.visualstudio.com/items?itemName=bibhasdn.django-html)
|
||||||
|
|
||||||
### DBeaver
|
### DBeaver
|
||||||
|
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ To reduce redundancy and help speed up development we encourage developers to ut
|
|||||||
esi
|
esi
|
||||||
evelinks
|
evelinks
|
||||||
eveonline
|
eveonline
|
||||||
|
notifications
|
||||||
testutils
|
testutils
|
||||||
```
|
```
|
||||||
|
|||||||
25
docs/development/tech_docu/api/notifications.rst
Normal file
25
docs/development/tech_docu/api/notifications.rst
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
======================
|
||||||
|
notifications
|
||||||
|
======================
|
||||||
|
|
||||||
|
The notifications package has an API for sending notifications.
|
||||||
|
|
||||||
|
Location: ``allianceauth.notifications``
|
||||||
|
|
||||||
|
.. automodule:: allianceauth.notifications.__init__
|
||||||
|
:members: notify
|
||||||
|
:undoc-members:
|
||||||
|
|
||||||
|
models
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. autoclass:: allianceauth.notifications.models.Notification
|
||||||
|
:members: LEVEL_CHOICES, mark_viewed, set_level
|
||||||
|
:undoc-members:
|
||||||
|
|
||||||
|
managers
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. autoclass:: allianceauth.notifications.managers.NotificationManager
|
||||||
|
:members: notify_user, user_unread_count
|
||||||
|
:undoc-members:
|
||||||
@@ -33,3 +33,21 @@ When you create an autogroup config you will be given the following options:
|
|||||||
- Corp/Alliance name source sets the source of the Corp/Alliance name used in creating the group name. Currently the options are Full name and Ticker.
|
- Corp/Alliance name source sets the source of the Corp/Alliance name used in creating the group name. Currently the options are Full name and Ticker.
|
||||||
|
|
||||||
- Replace spaces allows you to replace spaces in the autogroup name with the value in the Replace spaces with field. This can be blank.
|
- Replace spaces allows you to replace spaces in the autogroup name with the value in the Replace spaces with field. This can be blank.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
Auto Groups are configured via models in the Admin Interface, a user will require the `Staff` Flag in addition to the following permissions.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+-------------------------------------------+------------------+----------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+===========================================+==================+================+
|
||||||
|
| eve_autogroups.add_autogroupsconfig | Can create model | None. |
|
||||||
|
+-------------------------------------------+------------------+----------------+
|
||||||
|
| eve_autogroups.change_autogroupsconfig | Can edit model | None. |
|
||||||
|
+-------------------------------------------+------------------+----------------+
|
||||||
|
| eve_autogroups.delete_autogroupsconfig | Can delete model | None. |
|
||||||
|
+-------------------------------------------+------------------+----------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
There exists more models that will be automatically created and maintained by this module, they do not require end-user/admin interaction. `managedalliancegroup` `managedcorpgroups`
|
||||||
|
|||||||
@@ -102,11 +102,6 @@ To use this feature, users will require some of the following:
|
|||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
+---------------------------------------+------------------+----------------------------------------------------+
|
||||||
| corpstats.add_corpstats | Can create model | Can add new corpstats using an SSO token. |
|
| corpstats.add_corpstats | Can create model | Can add new corpstats using an SSO token. |
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
+---------------------------------------+------------------+----------------------------------------------------+
|
||||||
| corpstats.change_corpstats | Can edit model | None. |
|
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
|
||||||
| corpstats.remove_corpstats | Can delete model | None. |
|
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Users who add a Corp Stats with their token will be granted permissions to view it regardless of the above permissions. View permissions are interpreted in the "OR" sense: a user can view their corporation's Corp Stats without the `view_corp_corpstats` permission if they have the `view_alliance_corpstats` permission, same idea for their state. Note that these evaluate against the user's main character.
|
Users who add a Corp Stats with their token will be granted permissions to view it regardless of the above permissions. View permissions are interpreted in the "OR" sense: a user can view their corporation's Corp Stats without the `view_corp_corpstats` permission if they have the `view_alliance_corpstats` permission, same idea for their state. Note that these evaluate against the user's main character.
|
||||||
|
|||||||
@@ -9,3 +9,20 @@ The Fleet Activity Tracking (FAT) app allows you to track fleet participation.
|
|||||||
Fleet Activity Tracking requires access to the `esi-location.read_location.v1`, `esi-location.read_ship_type.v1`, and `esi-universe.read_structures.v1` SSO scopes. Update your application on the [EVE Developers site](https://developers.eveonline.com) to ensure these are available.
|
Fleet Activity Tracking requires access to the `esi-location.read_location.v1`, `esi-location.read_ship_type.v1`, and `esi-universe.read_structures.v1` SSO scopes. Update your application on the [EVE Developers site](https://developers.eveonline.com) to ensure these are available.
|
||||||
|
|
||||||
Add `'allianceauth.fleetactivitytracking',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
Add `'allianceauth.fleetactivitytracking',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To administer this feature, users will require some of the following.
|
||||||
|
|
||||||
|
Users do not require any permissions to interact with FAT Links created.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| auth.fleetactivitytracking | None | Create and Modify FATLinks |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| auth.fleetactivitytracking_statistics | None | Can view detailed statistics for corp models and other characters. |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
```
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ Any reviewer who can see the application can view the applicant's APIs if they p
|
|||||||
|
|
||||||
## Permissions
|
## Permissions
|
||||||
|
|
||||||
The following permissions have an effect on the website above and beyond their usual admin site functions.
|
To administer this feature, users will require some of the following.
|
||||||
|
|
||||||
|
Users do not require any permission to apply to a corporation and fill out the form.
|
||||||
|
|
||||||
```eval_rst
|
```eval_rst
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
+---------------------------------------+------------------+----------------------------------------------------+
|
||||||
@@ -54,13 +56,12 @@ The following permissions have an effect on the website above and beyond their u
|
|||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
+---------------------------------------+------------------+----------------------------------------------------+
|
||||||
| hrapplications.reject_applications | None | Can reject applications |
|
| hrapplications.reject_applications | None | Can reject applications |
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
+---------------------------------------+------------------+----------------------------------------------------+
|
||||||
| hrapplications.view_apis | None | Can view applicant API keys, and audit in Jacknife |
|
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
|
||||||
| hrapplications.add_applicationcomment | Can create model | Can comment on applications |
|
| hrapplications.add_applicationcomment | Can create model | Can comment on applications |
|
||||||
+---------------------------------------+------------------+----------------------------------------------------+
|
+---------------------------------------+------------------+----------------------------------------------------+
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A user with `auth.human_resources` can only see applications to their own corp.
|
||||||
|
|
||||||
Best practice is to bundle the `auth.human_resources` permission alongside the `hrapplications.approve_application` and `hrapplications.reject_application` permissions, as in isolation these don't make much sense.
|
Best practice is to bundle the `auth.human_resources` permission alongside the `hrapplications.approve_application` and `hrapplications.reject_application` permissions, as in isolation these don't make much sense.
|
||||||
|
|
||||||
## Models
|
## Models
|
||||||
|
|||||||
@@ -7,3 +7,17 @@ Fleet Operations is an app for organizing and communicating fleet schedules.
|
|||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add `'allianceauth.optimer',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
Add `'allianceauth.optimer',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use and administer this feature, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| auth.optimer_view | None | Can view Fleet Operation Timers |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| auth.optimer_manage | None | Can Manage Fleet Operation timers |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -37,3 +37,15 @@ The permissions audit page will give you an overview of all the users who have a
|
|||||||

|

|
||||||
|
|
||||||
Please note that users may appear multiple times if this permission is granted via multiple sources.
|
Please note that users may appear multiple times if this permission is granted via multiple sources.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this feature, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| permissions_tool.audit_permissions | None | Can view the Permissions Audit tool |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -7,3 +7,19 @@ Ship Replacement helps you to organize ship replacement programs (SRP) for your
|
|||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add `'allianceauth.srp',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
Add `'allianceauth.srp',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use and administer this feature, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+======================+==================+============================================================+
|
||||||
|
| auth.access_srp | None | Can create an SRP request from a fleet |
|
||||||
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
|
| auth.srp_management | None | Can Approve and Deny SRP requests, Can create an SRP Fleet |
|
||||||
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
|
| srp.add_srpfleetmain | Can Add Model | Can Create an SRP Fleet |
|
||||||
|
+----------------------+------------------+------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -7,3 +7,17 @@ Structure Timers helps you keep track of both offensive and defensive structure
|
|||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add `'allianceauth.timerboard',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
Add `'allianceauth.timerboard',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use and administer this feature, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| auth.timer_view | None | Can view Timerboard Timers |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| auth.timer_manage | None | Can Manage Timerboard timers |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -26,11 +26,6 @@ These logs contain the Date and Time the action was taken (in EVE/UTC), the user
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
```eval_rst
|
|
||||||
.. note::
|
|
||||||
There is no tracking for "Open" groups as members are able to freely join/leave these groups.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Group Leaders
|
## Group Leaders
|
||||||
|
|
||||||
Group leaders have the same abilities as users with the `group_management` permission, _however_, they will only be able to:
|
Group leaders have the same abilities as users with the `group_management` permission, _however_, they will only be able to:
|
||||||
@@ -38,4 +33,26 @@ Group leaders have the same abilities as users with the `group_management` permi
|
|||||||
- Approve requests for groups they are a leader of.
|
- Approve requests for groups they are a leader of.
|
||||||
- View the Group Membership and Group Members of groups they are leaders of.
|
- View the Group Membership and Group Members of groups they are leaders of.
|
||||||
|
|
||||||
This allows you to more finely control who has access to manage which groups. Currently it is not possible to add a Group as group leaders.
|
This allows you to more finely control who has access to manage which groups.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
Group Management should be mostly done using group leaders, a series of permissions are included below for thoroughness.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+================================+===================+====================================================================================+
|
||||||
|
| auth.group_management | None | Can Approve and Deny all Group Requests, Can view and manage all group memberships |
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
| groupmanagement.request_groups | None | Can Request Non-Public Groups |
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
| groupmanagement.add_group | Can Add Models | None |
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
| groupmanagement.change_group | Can Edit Models | None |
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
| groupmanagement.delete_group | Can Delete Models | None |
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
| groupmanagement.view_group | Can View Models | None |
|
||||||
|
+--------------------------------+-------------------+------------------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ This option still respects the Open option.
|
|||||||
|
|
||||||
### Open
|
### Open
|
||||||
|
|
||||||
When a group is toggled open, users who request to join the group will be immediately added to the group.
|
When a group is toggled open, users who request to join the group will be immediately added to the group.
|
||||||
|
|
||||||
If the group is not open, their request will have to be approved manually by someone with the group management role, or a group leader of that group.
|
If the group is not open, their request will have to be approved manually by someone with the group management role, or a group leader of that group.
|
||||||
|
|
||||||
@@ -48,3 +48,12 @@ When a user loses this permission, they will be removed from all groups _except_
|
|||||||
.. note::
|
.. note::
|
||||||
By default, the ``groupmanagement.request_groups`` permission is applied to the ``Member`` group. In most instances this, and perhaps adding it to the ``Blue`` group, should be all that is ever needed. It is unsupported and NOT advisable to apply this permission to a public group. See #697 for more information.
|
By default, the ``groupmanagement.request_groups`` permission is applied to the ``Member`` group. In most instances this, and perhaps adding it to the ``Blue`` group, should be all that is ever needed. It is unsupported and NOT advisable to apply this permission to a public group. See #697 for more information.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Auto Leave
|
||||||
|
|
||||||
|
By default in AA, Both requests and leaves for non-open groups must be approved by a group manager. If you wish to allow users to leave groups without requiring approvals, add the following lines to your `local.py`
|
||||||
|
|
||||||
|
```python
|
||||||
|
## Allows users to freely leave groups without requiring approval.
|
||||||
|
AUTO_LEAVE = True
|
||||||
|
```
|
||||||
@@ -10,4 +10,5 @@ Managing access to applications and services is one of the core functions of **A
|
|||||||
states
|
states
|
||||||
groups
|
groups
|
||||||
groupmanagement
|
groupmanagement
|
||||||
|
notifications
|
||||||
```
|
```
|
||||||
|
|||||||
14
docs/features/core/notifications.md
Normal file
14
docs/features/core/notifications.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Notifications
|
||||||
|
|
||||||
|
Alliance Auth has a build in notification system. The purpose of the notification system is to provide an easy and quick way to send messages to users of Auth. For example some apps are using it to inform users about results after long running tasks have completed and admins will automatically get notifications about system errors.
|
||||||
|
|
||||||
|
The number of unread notifications is shown to the user in the top menu. And the user can click on the notification count to open the notifications app.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Settings
|
||||||
|
|
||||||
|
The notifications app can be configured through settings.
|
||||||
|
|
||||||
|
- `NOTIFICATIONS_REFRESH_TIME`: The unread count in the top menu is automatically refreshed to keep the user informed about new notifications. This setting allows to set the time between each refresh in seconds. You can also set it to `0` to turn off automatic refreshing. Default: `30`
|
||||||
|
- `NOTIFICATIONS_MAX_PER_USER`: Maximum number of notifications that are stored per user. Older notifications are replaced by newer once. Default: `50`
|
||||||
@@ -26,7 +26,7 @@ DISCORD_SYNC_NAMES = False
|
|||||||
|
|
||||||
CELERYBEAT_SCHEDULE['discord.update_all_usernames'] = {
|
CELERYBEAT_SCHEDULE['discord.update_all_usernames'] = {
|
||||||
'task': 'discord.update_all_usernames',
|
'task': 'discord.update_all_usernames',
|
||||||
'schedule': crontab(hour='*/12'),
|
'schedule': crontab(minute=0, hour='*/12'),
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -139,6 +139,18 @@ Name Description
|
|||||||
=================================== ============================================================================================= =======
|
=================================== ============================================================================================= =======
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| discord.access_discord | None | Can Access the Discord Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### "Unknown Error" on Discord site when activating service
|
### "Unknown Error" on Discord site when activating service
|
||||||
|
|||||||
@@ -17,20 +17,26 @@ DISCOURSE_SSO_SECRET = ''
|
|||||||
|
|
||||||
## Install Docker
|
## Install Docker
|
||||||
|
|
||||||
wget -qO- https://get.docker.io/ | sh
|
```bash
|
||||||
|
wget -qO- https://get.docker.io/ | sh
|
||||||
|
```
|
||||||
|
|
||||||
## Install Discourse
|
## Install Discourse
|
||||||
|
|
||||||
### Download Discourse
|
### Download Discourse
|
||||||
|
|
||||||
mkdir /var/discourse
|
```bash
|
||||||
git clone https://github.com/discourse/discourse_docker.git /var/discourse
|
mkdir /var/discourse
|
||||||
|
git clone https://github.com/discourse/discourse_docker.git /var/discourse
|
||||||
|
```
|
||||||
|
|
||||||
### Configure
|
### Configure
|
||||||
|
|
||||||
cd /var/discourse
|
```bash
|
||||||
cp samples/standalone.yml containers/app.yml
|
cd /var/discourse
|
||||||
nano containers/app.yml
|
cp samples/standalone.yml containers/app.yml
|
||||||
|
nano containers/app.yml
|
||||||
|
```
|
||||||
|
|
||||||
Change the following:
|
Change the following:
|
||||||
|
|
||||||
@@ -40,38 +46,50 @@ Change the following:
|
|||||||
|
|
||||||
To install behind Apache/Nginx, look for this section:
|
To install behind Apache/Nginx, look for this section:
|
||||||
|
|
||||||
...
|
```ini
|
||||||
## which TCP/IP ports should this container expose?
|
...
|
||||||
expose:
|
## which TCP/IP ports should this container expose?
|
||||||
- "80:80" # fwd host port 80 to container port 80 (http)
|
expose:
|
||||||
...
|
- "80:80" # fwd host port 80 to container port 80 (http)
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
Change it to this:
|
Change it to this:
|
||||||
|
|
||||||
...
|
```ini
|
||||||
## which TCP/IP ports should this container expose?
|
...
|
||||||
expose:
|
## which TCP/IP ports should this container expose?
|
||||||
- "7890:80" # fwd host port 7890 to container port 80 (http)
|
expose:
|
||||||
...
|
- "7890:80" # fwd host port 7890 to container port 80 (http)
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
Or any other port will do, if taken. Remember this number.
|
Or any other port will do, if taken. Remember this number.
|
||||||
|
|
||||||
### Build and launch
|
### Build and launch
|
||||||
|
|
||||||
nano /etc/default/docker
|
```bash
|
||||||
|
nano /etc/default/docker
|
||||||
|
```
|
||||||
|
|
||||||
Uncomment this line:
|
Uncomment this line:
|
||||||
|
|
||||||
|
```ini
|
||||||
DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"
|
DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"
|
||||||
|
```
|
||||||
|
|
||||||
Restart Docker:
|
Restart Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
service docker restart
|
service docker restart
|
||||||
|
```
|
||||||
|
|
||||||
Now build:
|
Now build:
|
||||||
|
|
||||||
|
```bash
|
||||||
./launcher bootstrap app
|
./launcher bootstrap app
|
||||||
./launcher start app
|
./launcher start app
|
||||||
|
```
|
||||||
|
|
||||||
## Web Server Configuration
|
## Web Server Configuration
|
||||||
|
|
||||||
@@ -79,22 +97,26 @@ You will need to configure your web server to proxy requests to Discourse.
|
|||||||
|
|
||||||
A minimal Apache config might look like:
|
A minimal Apache config might look like:
|
||||||
|
|
||||||
<VirtualHost *:80>
|
```ini
|
||||||
ServerName discourse.example.com
|
<VirtualHost *:80>
|
||||||
ProxyPass / http://0.0.0.0:7890/
|
ServerName discourse.example.com
|
||||||
ProxyPassReverse / http://0.0.0.0:7890/
|
ProxyPass / http://0.0.0.0:7890/
|
||||||
</VirtualHost>
|
ProxyPassReverse / http://0.0.0.0:7890/
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
A minimal Nginx config might look like:
|
A minimal Nginx config might look like:
|
||||||
|
|
||||||
server {
|
```ini
|
||||||
listen 80;
|
server {
|
||||||
server_name discourse.example.com;
|
listen 80;
|
||||||
location / {
|
server_name discourse.example.com;
|
||||||
include proxy_params;
|
location / {
|
||||||
proxy_pass http://127.0.0.1:7890;
|
include proxy_params;
|
||||||
}
|
proxy_pass http://127.0.0.1:7890;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Configure API
|
## Configure API
|
||||||
|
|
||||||
@@ -102,8 +124,10 @@ A minimal Nginx config might look like:
|
|||||||
|
|
||||||
From the `/var/discourse` directory,
|
From the `/var/discourse` directory,
|
||||||
|
|
||||||
./launcher enter app
|
```bash
|
||||||
rake admin:create
|
./launcher enter app
|
||||||
|
rake admin:create
|
||||||
|
```
|
||||||
|
|
||||||
Follow prompts, being sure to answer `y` when asked to allow admin privileges.
|
Follow prompts, being sure to answer `y` when asked to allow admin privileges.
|
||||||
|
|
||||||
@@ -128,3 +152,15 @@ Navigate to `discourse.example.com` and log in. Back to the admin site, scroll d
|
|||||||
Save, now set `DISCOURSE_SSO_SECRET` in your auth project's settings file to the secure key you just put in Discourse.
|
Save, now set `DISCOURSE_SSO_SECRET` in your auth project's settings file to the secure key you just put in Discourse.
|
||||||
|
|
||||||
Finally run migrations and restart Gunicorn and Celery.
|
Finally run migrations and restart Gunicorn and Celery.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| discourse.access_discourse | None | Can Access the Discourse Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -200,13 +200,16 @@ python /home/allianceserver/myauth/manage.py migrate
|
|||||||
supervisorctl restart myauth:
|
supervisorctl restart myauth:
|
||||||
```
|
```
|
||||||
|
|
||||||
## Permissions on Auth
|
## Permissions
|
||||||
|
|
||||||
To enable the mumble service for users on Auth you need to give them the `access_mumble` permission. This permission is often added to the `Member` state.
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
```eval_rst
|
```eval_rst
|
||||||
.. note::
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
Note that groups will only be created on Mumble automatically when a user joins who is in the group.
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| mumble.access_mumble | None | Can Access the Mumble Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
## ACL configuration
|
## ACL configuration
|
||||||
@@ -296,4 +299,4 @@ Edit `authenticator.ini` and change (or add for older installs) This code block.
|
|||||||
avatar_enable = True
|
avatar_enable = True
|
||||||
;Get EvE avatar images from this location. {charid} will be filled in.
|
;Get EvE avatar images from this location. {charid} will be filled in.
|
||||||
ccp_avatar_url = https://images.evetech.net/characters/{charid}/portrait?size=32
|
ccp_avatar_url = https://images.evetech.net/characters/{charid}/portrait?size=32
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -20,18 +20,25 @@ BROADCAST_SERVICE_NAME = "broadcast"
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
Openfire require a Java 8 runtime environment.
|
Openfire require a Java 8 runtime environment.
|
||||||
|
|
||||||
Ubuntu:
|
Ubuntu:
|
||||||
|
|
||||||
apt-get install openjdk-8-jdk
|
```bash
|
||||||
|
apt-get install openjdk-8-jdk
|
||||||
|
```
|
||||||
|
|
||||||
CentOS:
|
CentOS:
|
||||||
|
|
||||||
yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel
|
```bash
|
||||||
|
yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel
|
||||||
|
```
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
### Download Installer
|
### Download Installer
|
||||||
|
|
||||||
Openfire is not available through repositories so we need to get a package from the developer.
|
Openfire is not available through repositories so we need to get a package from the developer.
|
||||||
|
|
||||||
On your PC, navigate to the [Ignite Realtime downloads section](https://www.igniterealtime.org/downloads/index.jsp), and under Openfire select Linux, click on the Ubuntu: Debian package (second from bottom of list, ends with .deb) or CentOS: RPM Package (no JRE bundled, as we have installed it on the host)
|
On your PC, navigate to the [Ignite Realtime downloads section](https://www.igniterealtime.org/downloads/index.jsp), and under Openfire select Linux, click on the Ubuntu: Debian package (second from bottom of list, ends with .deb) or CentOS: RPM Package (no JRE bundled, as we have installed it on the host)
|
||||||
@@ -42,27 +49,31 @@ In the console, ensure you’re in your user’s home directory: `cd ~`
|
|||||||
|
|
||||||
Now download the package. Replace the link below with the link you got earlier.
|
Now download the package. Replace the link below with the link you got earlier.
|
||||||
|
|
||||||
wget https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_4.2.3_all.deb
|
`wget https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_4.2.3_all.deb`
|
||||||
|
|
||||||
Now install from the package. Replace the filename with your filename (the last part of the download URL is the file name)
|
Now install from the package. Replace the filename with your filename (the last part of the download URL is the file name)
|
||||||
|
|
||||||
Ubuntu:
|
Ubuntu:
|
||||||
|
|
||||||
dpkg -i openfire_4.2.3_all.deb
|
`dpkg -i openfire_4.2.3_all.deb`
|
||||||
|
|
||||||
CentOS:
|
CentOS:
|
||||||
|
|
||||||
yum install -y openfire-4.2.3-1.noarch.rpm
|
`yum install -y openfire-4.2.3-1.noarch.rpm`
|
||||||
|
|
||||||
### Create Database
|
### Create Database
|
||||||
|
|
||||||
Performance is best when working from a SQL database. If you installed MySQL or MariaDB alongside your auth project, go ahead and create a database for Openfire:
|
Performance is best when working from a SQL database. If you installed MySQL or MariaDB alongside your auth project, go ahead and create a database for Openfire:
|
||||||
|
|
||||||
mysql -u root -p
|
```bash
|
||||||
create database alliance_jabber;
|
mysql -u root -p
|
||||||
grant all privileges on alliance_jabber . * to 'allianceserver'@'localhost';
|
create database alliance_jabber;
|
||||||
exit;
|
grant all privileges on alliance_jabber . * to 'allianceserver'@'localhost';
|
||||||
|
exit;
|
||||||
|
```
|
||||||
|
|
||||||
### Web Configuration
|
### Web Configuration
|
||||||
|
|
||||||
The remainder of the setup occurs through Openfire’s web interface. Navigate to http://example.com:9090, or if you’re behind CloudFlare, go straight to your server’s IP:9090.
|
The remainder of the setup occurs through Openfire’s web interface. Navigate to http://example.com:9090, or if you’re behind CloudFlare, go straight to your server’s IP:9090.
|
||||||
|
|
||||||
Select your language. I sure hope it’s English if you’re reading this guide.
|
Select your language. I sure hope it’s English if you’re reading this guide.
|
||||||
@@ -72,9 +83,10 @@ Under Server Settings, set the Domain to `example.com` replacing it with your ac
|
|||||||
Under Database Settings, select `Standard Database Connection`
|
Under Database Settings, select `Standard Database Connection`
|
||||||
|
|
||||||
On the next page, select `MySQL` from the dropdown list and change the following:
|
On the next page, select `MySQL` from the dropdown list and change the following:
|
||||||
- `[server]` is replaced by `127.0.0.1`
|
|
||||||
- `[database]` is replaced by the name of the database to be used by Openfire
|
- `[server]` is replaced by `127.0.0.1`
|
||||||
- enter the login details for your auth project's database user
|
- `[database]` is replaced by the name of the database to be used by Openfire
|
||||||
|
- enter the login details for your auth project's database user
|
||||||
|
|
||||||
If Openfire returns with a failed to connect error, re-check these settings. Note the lack of square brackets.
|
If Openfire returns with a failed to connect error, re-check these settings. Note the lack of square brackets.
|
||||||
|
|
||||||
@@ -85,12 +97,14 @@ Create an administrator account. The actual name is irrelevant, just don’t los
|
|||||||
Finally, log in to the console with your admin account.
|
Finally, log in to the console with your admin account.
|
||||||
|
|
||||||
Edit your auth project's settings file and enter the values you just set:
|
Edit your auth project's settings file and enter the values you just set:
|
||||||
- `JABBER_URL` is the pubic address of your jabber server
|
|
||||||
- `JABBER_PORT` is the port for clients to connect to (usually 5223)
|
- `JABBER_URL` is the pubic address of your jabber server
|
||||||
- `JABBER_SERVER` is the name of the jabber server. If you didn't alter it during install it'll usually be your domain (eg `example.com`)
|
- `JABBER_PORT` is the port for clients to connect to (usually 5223)
|
||||||
- `OPENFIRE_ADDRESS` is the web address of Openfire's web interface. Use http:// with port 9090 or https:// with port 9091 if you configure SSL in Openfire
|
- `JABBER_SERVER` is the name of the jabber server. If you didn't alter it during install it'll usually be your domain (eg `example.com`)
|
||||||
|
- `OPENFIRE_ADDRESS` is the web address of Openfire's web interface. Use http:// with port 9090 or https:// with port 9091 if you configure SSL in Openfire
|
||||||
|
|
||||||
### REST API Setup
|
### REST API Setup
|
||||||
|
|
||||||
Navigate to the `plugins` tab, and then `Available Plugins` on the left navigation bar. You’ll need to fetch the list of available plugins by clicking the link.
|
Navigate to the `plugins` tab, and then `Available Plugins` on the left navigation bar. You’ll need to fetch the list of available plugins by clicking the link.
|
||||||
|
|
||||||
Once loaded, press the green plus on the right for `REST API`.
|
Once loaded, press the green plus on the right for `REST API`.
|
||||||
@@ -109,12 +123,12 @@ Broadcasting requires a plugin. Navigate to the `plugins` tab, press the green p
|
|||||||
|
|
||||||
Navigate to the `Server` tab, `Server Manager` subtab, and select `System Properties`. Enter the following:
|
Navigate to the `Server` tab, `Server Manager` subtab, and select `System Properties`. Enter the following:
|
||||||
|
|
||||||
- Name: `plugin.broadcast.disableGroupPermissions`
|
- Name: `plugin.broadcast.disableGroupPermissions`
|
||||||
- Value: `True`
|
- Value: `True`
|
||||||
- Do not encrypt this property value
|
- Do not encrypt this property value
|
||||||
- Name: `plugin.broadcast.allowedUsers`
|
- Name: `plugin.broadcast.allowedUsers`
|
||||||
- Value: `broadcast@example.com`, replacing the domain name with yours
|
- Value: `broadcast@example.com`, replacing the domain name with yours
|
||||||
- Do not encrypt this property value
|
- Do not encrypt this property value
|
||||||
|
|
||||||
If you have troubles getting broadcasts to work, you can try setting the optional (you will need to add it) `BROADCAST_IGNORE_INVALID_CERT` setting to `True`. This will allow invalid certificates to be used when connecting to the Openfire server to send a broadcast.
|
If you have troubles getting broadcasts to work, you can try setting the optional (you will need to add it) `BROADCAST_IGNORE_INVALID_CERT` setting to `True`. This will allow invalid certificates to be used when connecting to the Openfire server to send a broadcast.
|
||||||
|
|
||||||
@@ -123,15 +137,29 @@ If you have troubles getting broadcasts to work, you can try setting the optiona
|
|||||||
Once all settings are entered, run migrations and restart Gunicorn and Celery.
|
Once all settings are entered, run migrations and restart Gunicorn and Celery.
|
||||||
|
|
||||||
### Group Chat
|
### Group Chat
|
||||||
|
|
||||||
Channels are available which function like a chat room. Access can be controlled either by password or ACL (not unlike mumble).
|
Channels are available which function like a chat room. Access can be controlled either by password or ACL (not unlike mumble).
|
||||||
|
|
||||||
Navigate to the `Group Chat` tab and select `Create New Room` from the left navigation bar.
|
Navigate to the `Group Chat` tab and select `Create New Room` from the left navigation bar.
|
||||||
- Room ID is a short, easy-to-type version of the room’s name users will connect to
|
|
||||||
- Room Name is the full name for the room
|
- Room ID is a short, easy-to-type version of the room’s name users will connect to
|
||||||
- Description is short text describing the room’s purpose
|
- Room Name is the full name for the room
|
||||||
- Set a password if you want password authentication
|
- Description is short text describing the room’s purpose
|
||||||
- Every other setting is optional. Save changes.
|
- Set a password if you want password authentication
|
||||||
|
- Every other setting is optional. Save changes.
|
||||||
|
|
||||||
Now select your new room. On the left navigation bar, select `Permissions`.
|
Now select your new room. On the left navigation bar, select `Permissions`.
|
||||||
|
|
||||||
ACL is achieved by assigning groups to each of the three tiers: `Owners`, `Admins` and `Members`. `Outcast` is the blacklist. You’ll usually only be assigning groups to the `Member` category.
|
ACL is achieved by assigning groups to each of the three tiers: `Owners`, `Admins` and `Members`. `Outcast` is the blacklist. You’ll usually only be assigning groups to the `Member` category.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| openfire.access_openfire | None | Can Access the Openfire Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
# phpBB3
|
# phpBB3
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
phpBB is a free PHP-based forum.
|
phpBB is a free PHP-based forum.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
phpBB3 requires PHP installed in your web server. Apache has `mod_php`, NGINX requires `php-fpm`. See [the official guide](https://www.phpbb.com/community/docs/INSTALL.html) for PHP package requirements.
|
phpBB3 requires PHP installed in your web server. Apache has `mod_php`, NGINX requires `php-fpm`. See [the official guide](https://www.phpbb.com/community/docs/INSTALL.html) for PHP package requirements.
|
||||||
|
|
||||||
## Prepare Your Settings
|
## Prepare Your Settings
|
||||||
|
|
||||||
In your auth project's settings file, do the following:
|
In your auth project's settings file, do the following:
|
||||||
- Add `'allianceauth.services.modules.phpbb3',` to your `INSTALLED_APPS` list
|
|
||||||
- Append the following to the bottom of the settings file:
|
- Add `'allianceauth.services.modules.phpbb3',` to your `INSTALLED_APPS` list
|
||||||
|
- Append the following to the bottom of the settings file:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# PHPBB3 Configuration
|
# PHPBB3 Configuration
|
||||||
@@ -25,32 +29,43 @@ DATABASES['phpbb3'] = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
### Prepare the Database
|
### Prepare the Database
|
||||||
|
|
||||||
Create a database to install phpBB3 in.
|
Create a database to install phpBB3 in.
|
||||||
|
|
||||||
mysql -u root -p
|
```bash
|
||||||
create database alliance_forum;
|
mysql -u root -p
|
||||||
grant all privileges on alliance_forum . * to 'allianceserver'@'localhost';
|
create database alliance_forum;
|
||||||
exit;
|
grant all privileges on alliance_forum . * to 'allianceserver'@'localhost';
|
||||||
|
exit;
|
||||||
|
```
|
||||||
|
|
||||||
Edit your auth project's settings file and fill out the `DATABASES['phpbb3']` part.
|
Edit your auth project's settings file and fill out the `DATABASES['phpbb3']` part.
|
||||||
|
|
||||||
### Download phpBB3
|
### Download phpBB3
|
||||||
|
|
||||||
phpBB3 is available as a zip from their website. Navigate to the website’s [downloads section](https://www.phpbb.com/downloads/) using your PC browser and copy the URL for the latest version zip.
|
phpBB3 is available as a zip from their website. Navigate to the website’s [downloads section](https://www.phpbb.com/downloads/) using your PC browser and copy the URL for the latest version zip.
|
||||||
|
|
||||||
In the console, navigate to your user’s home directory: `cd ~`
|
In the console, navigate to your user’s home directory: `cd ~`
|
||||||
|
|
||||||
Now download using wget, replacing the URL with the URL for the package you just retrieved
|
Now download using wget, replacing the URL with the URL for the package you just retrieved
|
||||||
|
|
||||||
wget https://www.phpbb.com/files/release/phpBB-3.2.2.zip
|
```bash
|
||||||
|
wget https://www.phpbb.com/files/release/phpBB-3.2.2.zip
|
||||||
|
```
|
||||||
|
|
||||||
This needs to be unpackaged. Unzip it, replacing the file name with that of the file you just downloaded
|
This needs to be unpackaged. Unzip it, replacing the file name with that of the file you just downloaded
|
||||||
|
|
||||||
unzip phpBB-3.2.2.zip
|
```bash
|
||||||
|
unzip phpBB-3.2.2.zip
|
||||||
|
```
|
||||||
|
|
||||||
Now we need to move this to our web directory. Usually `/var/www/forums`.
|
Now we need to move this to our web directory. Usually `/var/www/forums`.
|
||||||
|
|
||||||
mv phpBB3 /var/www/forums
|
```bash
|
||||||
|
mv phpBB3 /var/www/forums
|
||||||
|
```
|
||||||
|
|
||||||
The web server needs read/write permission to this folder
|
The web server needs read/write permission to this folder
|
||||||
|
|
||||||
@@ -64,49 +79,55 @@ Nginx: `chown -R nginx:nginx /var/www/forums`
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Configuring Web Server
|
### Configuring Web Server
|
||||||
|
|
||||||
You will need to configure you web server to serve PHPBB3 before proceeding with installation.
|
You will need to configure you web server to serve PHPBB3 before proceeding with installation.
|
||||||
|
|
||||||
A minimal Apache config file might look like:
|
A minimal Apache config file might look like:
|
||||||
|
|
||||||
<VirtualHost *:80>
|
```ini
|
||||||
ServerName forums.example.com
|
<VirtualHost *:80>
|
||||||
DocumentRoot /var/www/forums
|
ServerName forums.example.com
|
||||||
<Directory /var/www/forums>
|
DocumentRoot /var/www/forums
|
||||||
Require all granted
|
<Directory /var/www/forums>
|
||||||
DirectoryIndex index.php
|
Require all granted
|
||||||
</Directory>
|
DirectoryIndex index.php
|
||||||
</VirtualHost>
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
A minimal Nginx config file might look like:
|
A minimal Nginx config file might look like:
|
||||||
|
|
||||||
server {
|
```ini
|
||||||
listen 80;
|
server {
|
||||||
server_name forums.example.com;
|
listen 80;
|
||||||
root /var/www/forums;
|
server_name forums.example.com;
|
||||||
index index.php;
|
root /var/www/forums;
|
||||||
access_log /var/logs/forums.access.log;
|
index index.php;
|
||||||
|
access_log /var/logs/forums.access.log;
|
||||||
|
|
||||||
location ~ /(config\.php|common\.php|cache|files|images/avatars/upload|includes|store) {
|
location ~ /(config\.php|common\.php|cache|files|images/avatars/upload|includes|store) {
|
||||||
deny all;
|
deny all;
|
||||||
return 403;
|
return 403;
|
||||||
}
|
|
||||||
|
|
||||||
location ~* \.(gif|jpe?g|png|css)$ {
|
|
||||||
expires 30d;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
try_files $uri =404;
|
|
||||||
fastcgi_pass unix:/tmp/php.socket;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
include fastcgi_params;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location ~* \.(gif|jpe?g|png|css)$ {
|
||||||
|
expires 30d;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
try_files $uri =404;
|
||||||
|
fastcgi_pass unix:/tmp/php.socket;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Enter your forum's web address as the `PHPBB3_URL` setting in your auth project's settings file.
|
Enter your forum's web address as the `PHPBB3_URL` setting in your auth project's settings file.
|
||||||
|
|
||||||
### Web Install
|
### Web Install
|
||||||
|
|
||||||
Navigate to your forums web address where you will be presented with an installer.
|
Navigate to your forums web address where you will be presented with an installer.
|
||||||
|
|
||||||
Click on the `Install` tab.
|
Click on the `Install` tab.
|
||||||
@@ -114,12 +135,13 @@ Click on the `Install` tab.
|
|||||||
All the requirements should be met. Press `Start Install`.
|
All the requirements should be met. Press `Start Install`.
|
||||||
|
|
||||||
Under Database Settings, set the following:
|
Under Database Settings, set the following:
|
||||||
- Database Type is `MySQL`
|
|
||||||
- Database Server Hostname is `127.0.0.1`
|
- Database Type is `MySQL`
|
||||||
- Database Server Port is left blank
|
- Database Server Hostname is `127.0.0.1`
|
||||||
- Database Name is `alliance_forum`
|
- Database Server Port is left blank
|
||||||
- Database Username is your auth MySQL user, usually `allianceserver`
|
- Database Name is `alliance_forum`
|
||||||
- Database Password is this user’s password
|
- Database Username is your auth MySQL user, usually `allianceserver`
|
||||||
|
- Database Password is this user’s password
|
||||||
|
|
||||||
If you use a table prefix other than the standard `phpbb_` you need to add an additional setting to your auth project's settings file, `PHPBB3_TABLE_PREFIX = ''`, and enter the prefix.
|
If you use a table prefix other than the standard `phpbb_` you need to add an additional setting to your auth project's settings file, `PHPBB3_TABLE_PREFIX = ''`, and enter the prefix.
|
||||||
|
|
||||||
@@ -132,9 +154,12 @@ Everything from here should be intuitive.
|
|||||||
phpBB will then write its own config file.
|
phpBB will then write its own config file.
|
||||||
|
|
||||||
### Open the Forums
|
### Open the Forums
|
||||||
|
|
||||||
Before users can see the forums, we need to remove the install directory
|
Before users can see the forums, we need to remove the install directory
|
||||||
|
|
||||||
rm -rf /var/www/forums/install
|
```bash
|
||||||
|
rm -rf /var/www/forums/install
|
||||||
|
```
|
||||||
|
|
||||||
### Enabling Avatars
|
### Enabling Avatars
|
||||||
|
|
||||||
@@ -146,11 +171,26 @@ You can allow members to overwrite the portrait with a custom image if desired.
|
|||||||
|
|
||||||
Users generated via Alliance Auth do not have a default theme set. You will need to set this on the phpbb_users table in SQL
|
Users generated via Alliance Auth do not have a default theme set. You will need to set this on the phpbb_users table in SQL
|
||||||
|
|
||||||
mysql -u root -p
|
```bash
|
||||||
use alliance_forum;
|
mysql -u root -p
|
||||||
alter table phpbb_users change user_style user_style int not null default 1
|
use alliance_forum;
|
||||||
|
alter table phpbb_users change user_style user_style int not null default 1
|
||||||
|
```
|
||||||
|
|
||||||
If you would like to use a theme that is NOT prosilver or theme "1". You will need to deactivate prosilver, this will then fall over to the set forum wide default.
|
If you would like to use a theme that is NOT prosilver or theme "1". You will need to deactivate prosilver, this will then fall over to the set forum wide default.
|
||||||
|
|
||||||
### Prepare Auth
|
### Prepare Auth
|
||||||
|
|
||||||
Once settings have been configured, run migrations and restart Gunicorn and Celery.
|
Once settings have been configured, run migrations and restart Gunicorn and Celery.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| phpbb3.access_phpbb3 | None | Can Access the PHPBB3 Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
# SMF
|
# SMF
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
SMF is a free PHP-based forum.
|
SMF is a free PHP-based forum.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
SMF requires PHP installed in your web server. Apache has `mod_php`, NGINX requires `php-fpm`. More details can be found in the [SMF requirements page.](https://download.simplemachines.org/requirements.php)
|
SMF requires PHP installed in your web server. Apache has `mod_php`, NGINX requires `php-fpm`. More details can be found in the [SMF requirements page.](https://download.simplemachines.org/requirements.php)
|
||||||
|
|
||||||
## Prepare Your Settings
|
## Prepare Your Settings
|
||||||
|
|
||||||
In your auth project's settings file, do the following:
|
In your auth project's settings file, do the following:
|
||||||
- Add `'allianceauth.services.modules.smf',` to your `INSTALLED_APPS` list
|
- Add `'allianceauth.services.modules.smf',` to your `INSTALLED_APPS` list
|
||||||
- Append the following to the bottom of the settings file:
|
- Append the following to the bottom of the settings file:
|
||||||
@@ -25,7 +28,9 @@ DATABASES['smf'] = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
### Download SMF
|
### Download SMF
|
||||||
|
|
||||||
Using your browser, you can download the latest version of SMF to your desktop computer. All SMF downloads can be found at SMF Downloads. The latest recommended version will always be available at http://www.simplemachines.org/download/index.php/latest/install/. Retrieve the file location from the hyperlinked box icon for the zip full install, depending on your browser you may have a Copy Link or similar option in your right click menu.
|
Using your browser, you can download the latest version of SMF to your desktop computer. All SMF downloads can be found at SMF Downloads. The latest recommended version will always be available at http://www.simplemachines.org/download/index.php/latest/install/. Retrieve the file location from the hyperlinked box icon for the zip full install, depending on your browser you may have a Copy Link or similar option in your right click menu.
|
||||||
|
|
||||||
|
|
||||||
@@ -53,6 +58,7 @@ Nginx: `chown -R nginx:nginx /var/www/forums`
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Database Preparation
|
### Database Preparation
|
||||||
|
|
||||||
SMF needs a database. Create one:
|
SMF needs a database. Create one:
|
||||||
|
|
||||||
mysql -u root -p
|
mysql -u root -p
|
||||||
@@ -63,6 +69,7 @@ SMF needs a database. Create one:
|
|||||||
Enter the database information into the `DATABASES['smf']` section of your auth project's settings file.
|
Enter the database information into the `DATABASES['smf']` section of your auth project's settings file.
|
||||||
|
|
||||||
### Web Server Configuration
|
### Web Server Configuration
|
||||||
|
|
||||||
Your web server needs to be configured to serve SMF.
|
Your web server needs to be configured to serve SMF.
|
||||||
|
|
||||||
A minimal Apache config might look like:
|
A minimal Apache config might look like:
|
||||||
@@ -96,6 +103,7 @@ A minimal Nginx config might look like:
|
|||||||
Enter the web address to your forums into the `SMF_URL` setting in your auth project's settings file.
|
Enter the web address to your forums into the `SMF_URL` setting in your auth project's settings file.
|
||||||
|
|
||||||
### Web Install
|
### Web Install
|
||||||
|
|
||||||
Navigate to your forums address where you will be presented with an installer.
|
Navigate to your forums address where you will be presented with an installer.
|
||||||
|
|
||||||
Click on the `Install` tab.
|
Click on the `Install` tab.
|
||||||
@@ -103,16 +111,29 @@ Click on the `Install` tab.
|
|||||||
All the requirements should be met. Press `Start Install`.
|
All the requirements should be met. Press `Start Install`.
|
||||||
|
|
||||||
Under Database Settings, set the following:
|
Under Database Settings, set the following:
|
||||||
- Database Type is `MySQL`
|
- Database Type is `MySQL`
|
||||||
- Database Server Hostname is `127.0.0.1`
|
- Database Server Hostname is `127.0.0.1`
|
||||||
- Database Server Port is left blank
|
- Database Server Port is left blank
|
||||||
- Database Name is `alliance_smf`
|
- Database Name is `alliance_smf`
|
||||||
- Database Username is your auth MySQL user, usually `allianceserver`
|
- Database Username is your auth MySQL user, usually `allianceserver`
|
||||||
- Database Password is this user’s password
|
- Database Password is this user’s password
|
||||||
|
|
||||||
If you use a table prefix other than the standard `smf_` you need to add an additional setting to your auth project's settings file, `SMF_TABLE_PREFIX = ''`, and enter the prefix.
|
If you use a table prefix other than the standard `smf_` you need to add an additional setting to your auth project's settings file, `SMF_TABLE_PREFIX = ''`, and enter the prefix.
|
||||||
|
|
||||||
Follow the directions in the installer.
|
Follow the directions in the installer.
|
||||||
|
|
||||||
### Preparing Auth
|
### Preparing Auth
|
||||||
|
|
||||||
Once settings are entered, apply migrations and restart Gunicorn and Celery.
|
Once settings are entered, apply migrations and restart Gunicorn and Celery.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| smf.access_smf | None | Can Access the SMF Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
# TeamSpeak 3
|
# TeamSpeak 3
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
TeamSpeak3 is the most popular VOIP program for gamers.
|
TeamSpeak3 is the most popular VOIP program for gamers.
|
||||||
|
|
||||||
But have you considered using Mumble? Not only is it free, but it has features and performance far superior to Teamspeak3.
|
But have you considered using Mumble? Not only is it free, but it has features and performance far superior to Teamspeak3.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
Sticking with TS3? Alright, I tried.
|
Sticking with TS3? Alright, I tried.
|
||||||
|
|
||||||
### Prepare Your Settings
|
### Prepare Your Settings
|
||||||
|
|
||||||
In your auth project's settings file, do the following:
|
In your auth project's settings file, do the following:
|
||||||
- Add `'allianceauth.services.modules.teamspeak3',` to your `INSTALLED_APPS` list
|
|
||||||
- Append the following to the bottom of the settings file:
|
- Add `'allianceauth.services.modules.teamspeak3',` to your `INSTALLED_APPS` list
|
||||||
|
- Append the following to the bottom of the settings file:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Teamspeak3 Configuration
|
# Teamspeak3 Configuration
|
||||||
@@ -29,51 +33,70 @@ CELERYBEAT_SCHEDULE['run_ts3_group_update'] = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Download Installer
|
### Download Installer
|
||||||
|
|
||||||
To install we need a copy of the server. You can find the latest version from [this dl server](http://dl.4players.de/ts/releases/) (I’d recommend getting the latest stable version – find this version number from the [TeamSpeak site](https://www.teamspeak.com/downloads#)). Be sure to get a link to the Linux version.
|
To install we need a copy of the server. You can find the latest version from [this dl server](http://dl.4players.de/ts/releases/) (I’d recommend getting the latest stable version – find this version number from the [TeamSpeak site](https://www.teamspeak.com/downloads#)). Be sure to get a link to the Linux version.
|
||||||
|
|
||||||
Download the server, replacing the link with the link you got earlier.
|
Download the server, replacing the link with the link you got earlier.
|
||||||
|
|
||||||
http://dl.4players.de/ts/releases/3.1.1/teamspeak3-server_linux_amd64-3.1.1.tar.bz2
|
```text
|
||||||
|
http://dl.4players.de/ts/releases/3.13.2/teamspeak3-server_linux_amd64-3.13.2.tar.bz2
|
||||||
|
```
|
||||||
|
|
||||||
Now we need to extract the file.
|
Now we need to extract the file.
|
||||||
|
|
||||||
tar -xf teamspeak3-server_linux_amd64-3.1.0.tar.bz2
|
```bash
|
||||||
|
tar -xf teamspeak3-server_linux_amd64-3.1.0.tar.bz2
|
||||||
|
```
|
||||||
|
|
||||||
### Create User
|
### Create User
|
||||||
|
|
||||||
TeamSpeak needs its own user.
|
TeamSpeak needs its own user.
|
||||||
|
|
||||||
adduser --disabled-login teamspeak
|
```bash
|
||||||
|
adduser --disabled-login teamspeak
|
||||||
|
```
|
||||||
|
|
||||||
### Install Binary
|
### Install Binary
|
||||||
|
|
||||||
Now we move the server binary somewhere more accessible and change its ownership to the new user.
|
Now we move the server binary somewhere more accessible and change its ownership to the new user.
|
||||||
|
|
||||||
mv teamspeak3-server_linux_amd64 /usr/local/teamspeak
|
```bash
|
||||||
chown -R teamspeak:teamspeak /usr/local/teamspeak
|
mv teamspeak3-server_linux_amd64 /usr/local/teamspeak
|
||||||
|
chown -R teamspeak:teamspeak /usr/local/teamspeak
|
||||||
|
```
|
||||||
|
|
||||||
### Startup
|
### Startup
|
||||||
|
|
||||||
Now we generate a startup script so TeamSpeak comes up with the server.
|
Now we generate a startup script so TeamSpeak comes up with the server.
|
||||||
|
|
||||||
ln -s /usr/local/teamspeak/ts3server_startscript.sh /etc/init.d/teamspeak
|
```bash
|
||||||
update-rc.d teamspeak defaults
|
ln -s /usr/local/teamspeak/ts3server_startscript.sh /etc/init.d/teamspeak
|
||||||
|
update-rc.d teamspeak defaults
|
||||||
|
```
|
||||||
|
|
||||||
Finally we start the server.
|
Finally we start the server.
|
||||||
|
|
||||||
service teamspeak start
|
```bash
|
||||||
|
service teamspeak start
|
||||||
|
```
|
||||||
|
|
||||||
### Update Settings
|
### Update Settings
|
||||||
|
|
||||||
The console will spit out a block of text. If it does not appear, it can be found with `service teamspeak status`. **SAVE THIS**.
|
The console will spit out a block of text. If it does not appear, it can be found with `service teamspeak status`. **SAVE THIS**.
|
||||||
|
|
||||||
If you plan on claiming the ServerAdmin token, do so with a different TeamSpeak client profile than the one used for your auth account, or you will lose your admin status.
|
If you plan on claiming the ServerAdmin token, do so with a different TeamSpeak client profile than the one used for your auth account, or you will lose your admin status.
|
||||||
|
|
||||||
Edit the settings you added to your auth project's settings file earlier, entering the following:
|
Edit the settings you added to your auth project's settings file earlier, entering the following:
|
||||||
- `TEAMSPEAK3_SERVERQUERY_USER` is `loginname` from that block of text it just spat out (usually `serveradmin`)
|
|
||||||
- `TEAMSPEAK3_SERVERQUERY_PASSWORD` is `password` from that block of text it just spat out
|
- `TEAMSPEAK3_SERVERQUERY_USER` is `loginname` from that block of text it just spat out (usually `serveradmin`)
|
||||||
- `TEAMSPEAK_VIRTUAL_SERVER` is the virtual server ID of the server to be managed - it will only ever not be 1 if your server is hosted by a professional company
|
- `TEAMSPEAK3_SERVERQUERY_PASSWORD` is `password` from that block of text it just spat out
|
||||||
- `TEAMSPEAK3_PUBLIC_URL` is the public address of your TeamSpeak server. Do not include any leading http:// or teamspeak://
|
- `TEAMSPEAK_VIRTUAL_SERVER` is the virtual server ID of the server to be managed - it will only ever not be 1 if your server is hosted by a professional company
|
||||||
|
- `TEAMSPEAK3_PUBLIC_URL` is the public address of your TeamSpeak server. Do not include any leading http:// or teamspeak://
|
||||||
|
|
||||||
Once settings are entered, run migrations and restart Gunicorn and Celery.
|
Once settings are entered, run migrations and restart Gunicorn and Celery.
|
||||||
|
|
||||||
### Generate User Account
|
### Generate User Account
|
||||||
|
|
||||||
And now we can generate ourselves a user account. Navigate to the services in Alliance Auth for your user account and press the checkmark for TeamSpeak 3.
|
And now we can generate ourselves a user account. Navigate to the services in Alliance Auth for your user account and press the checkmark for TeamSpeak 3.
|
||||||
|
|
||||||
Click the URL provided to automatically connect to our server. It will prompt you to redeem the serveradmin token, enter the `token` from startup.
|
Click the URL provided to automatically connect to our server. It will prompt you to redeem the serveradmin token, enter the `token` from startup.
|
||||||
@@ -82,7 +105,9 @@ Click the URL provided to automatically connect to our server. It will prompt yo
|
|||||||
|
|
||||||
Now we need to make groups. AllianceAuth handles groups in teamspeak differently: instead of creating groups it creates an association between groups in TeamSpeak and groups in AllianceAuth. Go ahead and make the groups you want to associate with auth groups, keeping in mind multiple TeamSpeak groups can be associated with a single auth group.
|
Now we need to make groups. AllianceAuth handles groups in teamspeak differently: instead of creating groups it creates an association between groups in TeamSpeak and groups in AllianceAuth. Go ahead and make the groups you want to associate with auth groups, keeping in mind multiple TeamSpeak groups can be associated with a single auth group.
|
||||||
|
|
||||||
Navigate back to the AllianceAuth admin interface (example.com/admin) and under `Services`, select `Auth / TS Groups`. In the top-right corner click `Add`.
|
Navigate back to the AllianceAuth admin interface (example.com/admin) and under `Teamspeak3`, select `Auth / TS Groups`.
|
||||||
|
|
||||||
|
In the top-right corner click, first click on `Update TS3 Groups` to fetch the newly created server groups from TS3 (this may take a minute to complete). Then click on `Add Auth / TS Group` to link Auth groups with TS3 server groups.
|
||||||
|
|
||||||
The dropdown box provides all auth groups. Select one and assign TeamSpeak groups from the panels below. If these panels are empty, wait a minute for the database update to run, or see the [troubleshooting section](#ts-group-models-not-populating-on-admin-site) below.
|
The dropdown box provides all auth groups. Select one and assign TeamSpeak groups from the panels below. If these panels are empty, wait a minute for the database update to run, or see the [troubleshooting section](#ts-group-models-not-populating-on-admin-site) below.
|
||||||
|
|
||||||
@@ -95,14 +120,29 @@ Using the advanced permissions editor, ensure the `Guest` group has the permissi
|
|||||||
To enable advanced permissions, on your client go to the `Tools` menu, `Application`, and under the `Misc` section, tick `Advanced permission system`
|
To enable advanced permissions, on your client go to the `Tools` menu, `Application`, and under the `Misc` section, tick `Advanced permission system`
|
||||||
|
|
||||||
### TS group models not populating on admin site
|
### TS group models not populating on admin site
|
||||||
The method which populates these runs every 30 minutes. To populate manually, start a django shell:
|
|
||||||
|
|
||||||
python manage.py shell
|
The method which populates these runs every 30 minutes. To populate manually you start the process from the admin site or from the Django shell.
|
||||||
|
|
||||||
And execute the update:
|
#### Admin Site
|
||||||
|
|
||||||
from allianceauth.services.modules.teamspeak3.tasks import Teamspeak3Tasks
|
Navigate to the AllianceAuth admin interface and under `Teamspeak3`, select `Auth / TS Groups`.
|
||||||
Teamspeak3Tasks.run_ts3_group_update()
|
|
||||||
|
Then, in the top-right corner click, click on `Update TS3 Groups` to start the process of fetching the server groups from TS3 (this may take a minute to complete).
|
||||||
|
|
||||||
|
#### Django Shell
|
||||||
|
|
||||||
|
Start a django shell with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python manage.py shell
|
||||||
|
```
|
||||||
|
|
||||||
|
And execute the update as follows:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from allianceauth.services.modules.teamspeak3.tasks import Teamspeak3Tasks
|
||||||
|
Teamspeak3Tasks.run_ts3_group_update()
|
||||||
|
```
|
||||||
|
|
||||||
Ensure that command does not return an error.
|
Ensure that command does not return an error.
|
||||||
|
|
||||||
@@ -129,3 +169,23 @@ The serverquery account login specified in local.py is incorrect. Please verify
|
|||||||
### `2568 insufficient client permissions`
|
### `2568 insufficient client permissions`
|
||||||
|
|
||||||
This usually occurs if you've created a separate serverquery user to use with auth. It has not been assigned sufficient permissions to complete all the tasks required of it. The full list of required permissions is not known, so assign liberally.
|
This usually occurs if you've created a separate serverquery user to use with auth. It has not been assigned sufficient permissions to complete all the tasks required of it. The full list of required permissions is not known, so assign liberally.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use and configure this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| teamspeak.access_teamspeak | None | Can Access the TeamSpeak Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| teamspeak.add_authts | Can Add Model | None |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| teamspeak.change_authts | Can Change Model | None |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| teamspeak.delete_authts | Can Delete Model | None |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| teamspeak.view_authts | Can View Model | None |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
# XenForo
|
# XenForo
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
[XenForo](https://xenforo.com/) is a popular paid forum. This guide will assume that you already have XenForo installed with a valid license (please keep in mind that XenForo is not free nor open-source, therefore you need to purchase a license first). If you come across any problems related with the installation of XenForo please contact their support service.
|
[XenForo](https://xenforo.com/) is a popular paid forum. This guide will assume that you already have XenForo installed with a valid license (please keep in mind that XenForo is not free nor open-source, therefore you need to purchase a license first). If you come across any problems related with the installation of XenForo please contact their support service.
|
||||||
|
|
||||||
## Prepare Your Settings
|
## Prepare Your Settings
|
||||||
|
|
||||||
In your auth project's settings file, do the following:
|
In your auth project's settings file, do the following:
|
||||||
- Add `'allianceauth.services.modules.xenforo',` to your `INSTALLED_APPS` list
|
|
||||||
- Append the following to your local.py settings file:
|
- Add `'allianceauth.services.modules.xenforo',` to your `INSTALLED_APPS` list
|
||||||
|
- Append the following to your local.py settings file:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# XenForo Configuration
|
# XenForo Configuration
|
||||||
@@ -39,3 +42,15 @@ The settings you created earlier now need to be filled out.
|
|||||||
`XENFORO_API_KEY` is the API key value you set earlier.
|
`XENFORO_API_KEY` is the API key value you set earlier.
|
||||||
|
|
||||||
Once these are entered, run migrations and restart Gunicorn and Celery.
|
Once these are entered, run migrations and restart Gunicorn and Celery.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
To use this service, users will require some of the following.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
| Permission | Admin Site | Auth Site |
|
||||||
|
+=======================================+==================+==========================================================================+
|
||||||
|
| xenforo.access_xenforo | None | Can Access the XenForo Service |
|
||||||
|
+---------------------------------------+------------------+--------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ CREATE DATABASE alliance_auth CHARACTER SET utf8mb4;
|
|||||||
GRANT ALL PRIVILEGES ON alliance_auth . * TO 'allianceserver'@'localhost';
|
GRANT ALL PRIVILEGES ON alliance_auth . * TO 'allianceserver'@'localhost';
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Once your database is set up, you can leave the SQL shell with `exit`.
|
||||||
|
|
||||||
Add timezone tables to your mysql installation:
|
Add timezone tables to your mysql installation:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -177,7 +179,7 @@ source /home/allianceserver/venv/auth/bin/activate
|
|||||||
|
|
||||||
You need to have a dedicated Eve SSO app for Alliance auth. Please go to [EVE Developer](https://developers.eveonline.com/applications) to create one.
|
You need to have a dedicated Eve SSO app for Alliance auth. Please go to [EVE Developer](https://developers.eveonline.com/applications) to create one.
|
||||||
|
|
||||||
For **scopes** your SSO app needs to have at least `publicData`. Additional scopes depends on which Alliance Auth apps you will be using. For convenience we recommend adding all available ESO scopes to your SSO app. Note that Alliance Auth will always ask the users to approve specific scopes before they are used.
|
For **scopes** your SSO app needs to have at least `publicData`. Additional scopes depends on which Alliance Auth apps you will be using. For convenience, we recommend adding all available ESO scopes to your SSO app. Note that Alliance Auth will always ask the users to approve specific scopes before they are used.
|
||||||
|
|
||||||
As **callback URL** you want to define the URL of your Alliance Auth site plus the route: `/sso/callback`. Example for a valid callback URL: `https://auth.example.com/sso/callback`
|
As **callback URL** you want to define the URL of your Alliance Auth site plus the route: `/sso/callback`. Example for a valid callback URL: `https://auth.example.com/sso/callback`
|
||||||
|
|
||||||
@@ -236,7 +238,7 @@ Check to ensure your settings are valid.
|
|||||||
python /home/allianceserver/myauth/manage.py check
|
python /home/allianceserver/myauth/manage.py check
|
||||||
```
|
```
|
||||||
|
|
||||||
And finally ensure the allianceserver user has read/write permissions to this directory before proceeding.
|
Finally, ensure the allianceserver user has read/write permissions to this directory before proceeding.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
chown -R allianceserver:allianceserver /home/allianceserver/myauth
|
chown -R allianceserver:allianceserver /home/allianceserver/myauth
|
||||||
@@ -244,7 +246,7 @@ chown -R allianceserver:allianceserver /home/allianceserver/myauth
|
|||||||
|
|
||||||
## Services
|
## Services
|
||||||
|
|
||||||
Alliance Auth needs some additional services to run, which we will setup and configure next.
|
Alliance Auth needs some additional services to run, which we will set up and configure next.
|
||||||
|
|
||||||
### Gunicorn
|
### Gunicorn
|
||||||
|
|
||||||
@@ -275,7 +277,7 @@ systemctl enable supervisord.service
|
|||||||
systemctl start supervisord.service
|
systemctl start supervisord.service
|
||||||
```
|
```
|
||||||
|
|
||||||
Once installed it needs a configuration file to know which processes to watch. Your Alliance Auth project comes with a ready-to-use template which will ensure the Celery workers, Celery task scheduler and Gunicorn are all running.
|
Once installed, it needs a configuration file to know which processes to watch. Your Alliance Auth project comes with a ready-to-use template which will ensure the Celery workers, Celery task scheduler and Gunicorn are all running.
|
||||||
|
|
||||||
Ubuntu:
|
Ubuntu:
|
||||||
|
|
||||||
@@ -289,7 +291,7 @@ CentOS:
|
|||||||
ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
|
ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
|
||||||
```
|
```
|
||||||
|
|
||||||
And activate it with `supervisorctl reload`.
|
Activate it with `supervisorctl reload`.
|
||||||
|
|
||||||
You can check the status of the processes with `supervisorctl status`. Logs from these processes are available in `/home/allianceserver/myauth/log` named by process.
|
You can check the status of the processes with `supervisorctl status`. Logs from these processes are available in `/home/allianceserver/myauth/log` named by process.
|
||||||
|
|
||||||
@@ -304,11 +306,11 @@ You can check the status of the processes with `supervisorctl status`. Logs from
|
|||||||
|
|
||||||
Once installed, decide on whether you're going to use [NGINX](nginx.md) or [Apache](apache.md) and follow the respective guide.
|
Once installed, decide on whether you're going to use [NGINX](nginx.md) or [Apache](apache.md) and follow the respective guide.
|
||||||
|
|
||||||
Note that Alliance Auth is designed to run with web servers on HTTPS. While running on HTTP is technically possible, it is not recommended for production use and some functions (e.g. Email confirmation links) will not work properly.
|
Note that Alliance Auth is designed to run with web servers on HTTPS. While running on HTTP is technically possible, it is not recommended for production use, and some functions (e.g. Email confirmation links) will not work properly.
|
||||||
|
|
||||||
## Superuser
|
## Superuser
|
||||||
|
|
||||||
Before using your auth site it is essential to create a superuser account. This account will have all permissions in Alliance Auth. It's OK to use this as your personal auth account.
|
Before using your auth site, it is essential to create a superuser account. This account will have all permissions in Alliance Auth. It's OK to use this as your personal auth account.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python /home/allianceserver/myauth/manage.py createsuperuser
|
python /home/allianceserver/myauth/manage.py createsuperuser
|
||||||
@@ -316,7 +318,7 @@ python /home/allianceserver/myauth/manage.py createsuperuser
|
|||||||
|
|
||||||
The superuser account is accessed by logging in via the admin site at `https://example.com/admin`.
|
The superuser account is accessed by logging in via the admin site at `https://example.com/admin`.
|
||||||
|
|
||||||
If you intend to use this account as your personal auth account you need to add a main character. Navigate to the normal user dashboard (at `https://example.com`) after logging in via the admin site and select `Change Main`. Once a main character has been added it is possible to use SSO to login to this account.
|
If you intend to use this account as your personal auth account you need to add a main character. Navigate to the normal user dashboard (at `https://example.com`) after logging in via the admin site and select `Change Main`. Once a main character has been added, it is possible to use SSO to login to this account.
|
||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
|
|
||||||
@@ -340,7 +342,7 @@ Some releases come with new or changed models. Update your database to reflect t
|
|||||||
python /home/allianceserver/myauth/manage.py migrate
|
python /home/allianceserver/myauth/manage.py migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally some releases come with new or changed static files. Run the following command to update your static files folder:
|
Finally, some releases come with new or changed static files. Run the following command to update your static files folder:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python /home/allianceserver/myauth/manage.py collectstatic
|
python /home/allianceserver/myauth/manage.py collectstatic
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
# Adding and Removing Apps
|
# App Maintenance
|
||||||
|
|
||||||
|
## Adding and Removing Apps
|
||||||
|
|
||||||
Your auth project is just a regular Django project - you can add in [other Django apps](https://djangopackages.org/) as desired. Most come with dedicated setup guides, but here is the general procedure:
|
Your auth project is just a regular Django project - you can add in [other Django apps](https://djangopackages.org/) as desired. Most come with dedicated setup guides, but here is the general procedure:
|
||||||
|
|
||||||
@@ -8,3 +10,17 @@ Your auth project is just a regular Django project - you can add in [other Djang
|
|||||||
4. restart AA with `supervisorctl restart myauth:`
|
4. restart AA with `supervisorctl restart myauth:`
|
||||||
|
|
||||||
If you ever want to remove an app, you should first clear it from the database to avoid dangling foreign keys: `python manage.py migrate appname zero`. Then you can remove it from your auth project's `INSTALLED_APPS` list.
|
If you ever want to remove an app, you should first clear it from the database to avoid dangling foreign keys: `python manage.py migrate appname zero`. Then you can remove it from your auth project's `INSTALLED_APPS` list.
|
||||||
|
|
||||||
|
## Permission Cleanup
|
||||||
|
|
||||||
|
Mature Alliance Auth installations, or those with actively developed extensions may find themselves with stale or duplicated Permission models.
|
||||||
|
|
||||||
|
This can make it confusing for admins to apply the right permissions, contribute to larger queries in backend management or simply look unsightly.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python manage.py remove_stale_contenttypes --include-stale-apps
|
||||||
|
```
|
||||||
|
|
||||||
|
This inbuilt Django command will step through each contenttype and offer to delete it, displaying what exactly this will cascade to delete. Pay attention and ensure you understand exactly what is being removed before answering `yes`.
|
||||||
|
|
||||||
|
This should only cleanup uninstalled apps, deprecated permissions within apps should be cleaned up using Data Migrations by each responsible application.
|
||||||
|
|||||||
8
setup.py
8
setup.py
@@ -20,13 +20,13 @@ install_requires = [
|
|||||||
|
|
||||||
'redis>=3.3.1,<4.0.0',
|
'redis>=3.3.1,<4.0.0',
|
||||||
'celery>=4.3.0,<5.0.0,!=4.4.4', # 4.4.4 is missing a dependency
|
'celery>=4.3.0,<5.0.0,!=4.4.4', # 4.4.4 is missing a dependency
|
||||||
'celery_once',
|
'celery_once>=2.0.1',
|
||||||
|
|
||||||
'django>=3.1.1,<4.0.0',
|
'django>=3.1.1,<3.2.0',
|
||||||
'django-bootstrap-form',
|
'django-bootstrap-form',
|
||||||
'django-registration>=3.1',
|
'django-registration>=3.1',
|
||||||
'django-sortedm2m',
|
'django-sortedm2m',
|
||||||
'django-redis-cache>=2.1.0,<3.0.0,!=2.1.3', # 2.1.3 != Django 3 (Issue 1264)
|
'django-redis-cache>=3.0.0',
|
||||||
'django-celery-beat>=2.0.0',
|
'django-celery-beat>=2.0.0',
|
||||||
|
|
||||||
'openfire-restapi',
|
'openfire-restapi',
|
||||||
@@ -71,7 +71,7 @@ setup(
|
|||||||
classifiers=[
|
classifiers=[
|
||||||
'Environment :: Web Environment',
|
'Environment :: Web Environment',
|
||||||
'Framework :: Django',
|
'Framework :: Django',
|
||||||
'Framework :: Django :: 2.2',
|
'Framework :: Django :: 3.1',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
|
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
|
||||||
'Operating System :: POSIX :: Linux',
|
'Operating System :: POSIX :: Linux',
|
||||||
|
|||||||
Reference in New Issue
Block a user