Merge branch 'master' of gitlab.com:allianceauth/allianceauth into v4.x

This commit is contained in:
Ariel Rin 2023-12-08 14:49:56 +10:00
commit 20067c1133
No known key found for this signature in database
94 changed files with 2865 additions and 1642 deletions

View File

@ -7,11 +7,11 @@ version: 2
# Set the version of Python and other tools you might need # Set the version of Python and other tools you might need
build: build:
os: ubuntu-20.04 os: ubuntu-22.04
apt_packages: apt_packages:
- redis - redis
tools: tools:
python: "3.8" python: "3.11"
# Build documentation in the docs/ directory with Sphinx # Build documentation in the docs/ directory with Sphinx
sphinx: sphinx:
@ -20,7 +20,7 @@ sphinx:
# Optionally build your docs in additional formats such as PDF and ePub # Optionally build your docs in additional formats such as PDF and ePub
formats: all formats: all
# Optionally set the version of Python and requirements required to build your docs # Python requirements required to build your docs
python: python:
install: install:
- method: pip - method: pip

View File

@ -1,5 +1,5 @@
[main] [main]
host = https://www.transifex.com host = https://app.transifex.com
lang_map = zh-Hans: zh_Hans lang_map = zh-Hans: zh_Hans
[o:alliance-auth:p:alliance-auth:r:django-po] [o:alliance-auth:p:alliance-auth:r:django-po]

View File

@ -1,10 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = zh-Hans:zh_Hans
[alliance-auth.django-po]
file_filter = allianceauth/locale/<lang>/LC_MESSAGES/django.po
minimum_perc = 0
source_file = allianceauth/locale/en/LC_MESSAGES/django.po
source_lang = en
type = PO

10
.tx/transifex.yml Normal file
View File

@ -0,0 +1,10 @@
filters:
- filter_type: file
file_format: PO
source_file: allianceauth/locale/en/LC_MESSAGES/django.po
source_language: en
translation_files_expression: allianceauth/locale/<lang>/LC_MESSAGES/django.po
settings:
language_mapping:
zh-Hans: zh_Hans

View File

@ -17,7 +17,7 @@ An auth system for EVE Online to help in-game organizations manage online servic
- [Documentation](http://allianceauth.rtfd.io) - [Documentation](http://allianceauth.rtfd.io)
- [Support](#support) - [Support](#support)
- [Release Notes](https://gitlab.com/allianceauth/allianceauth/-/releases) - [Release Notes](https://gitlab.com/allianceauth/allianceauth/-/releases)
- [Developer Team](#developer-team) - [Developer Team](#development-team)
- [Contributing](#contributing) - [Contributing](#contributing)
## Overview ## Overview

View File

@ -1,6 +1,10 @@
import functools
from django import forms from django import forms
from django.contrib.auth.models import Group from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.auth.models import Group, User
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db.models.functions import Lower
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -8,6 +12,39 @@ from .models import ReservedGroupName
class GroupAdminForm(forms.ModelForm): class GroupAdminForm(forms.ModelForm):
users = forms.ModelMultipleChoiceField(
queryset=User.objects.order_by(Lower('username')),
required=False,
widget=FilteredSelectMultiple(verbose_name=_("Users"), is_stacked=False),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields["users"].initial = self.instance.user_set.all()
def save(self, commit=True):
group: Group = super().save(commit=False)
if commit:
group.save()
users = self.cleaned_data["users"]
if group.pk:
self._save_m2m_and_users(group, users)
else:
self.save_m2m = functools.partial(
self._save_m2m_and_users, group=group, users=users
)
return group
def _save_m2m_and_users(self, group, users):
"""Save m2m relations incl. users."""
group.user_set.set(users)
self._save_m2m()
def clean_name(self): def clean_name(self):
my_name = self.cleaned_data['name'] my_name = self.cleaned_data['name']
if ReservedGroupName.objects.filter(name__iexact=my_name).exists(): if ReservedGroupName.objects.filter(name__iexact=my_name).exists():

View File

@ -1,8 +1,7 @@
from typing import Set from typing import Set
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import Group from django.contrib.auth.models import Group, User
from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -14,7 +13,7 @@ from allianceauth.notifications import notify
class GroupRequest(models.Model): class GroupRequest(models.Model):
"""Request from a user for joining or leaving a group.""" """Request from a user for joining or leaving a group."""
leave_request = models.BooleanField(default=0) leave_request = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE)
@ -49,7 +48,7 @@ class RequestLog(models.Model):
request_type = models.BooleanField(null=True) request_type = models.BooleanField(null=True)
group = models.ForeignKey(Group, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE)
request_info = models.CharField(max_length=254) request_info = models.CharField(max_length=254)
action = models.BooleanField(default=0) action = models.BooleanField(default=False)
request_actor = models.ForeignKey(User, on_delete=models.CASCADE) request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True) date = models.DateTimeField(auto_now_add=True)

View File

@ -26,12 +26,20 @@
<a class="nav-link" id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave" type="button" role="tab" aria-controls="leave" aria-selected="false"> <a class="nav-link" id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave" type="button" role="tab" aria-controls="leave" aria-selected="false">
{% translate "Leave Requests" %} {% translate "Leave Requests" %}
{% if not show_leave_tab %}
<li>
<a data-toggle="tab" href="#leave">
{% translate "Leave Requests" %}
{% if leaverequests %} {% if leaverequests %}
<span class="badge bg-secondary">{{ leaverequests|length }}</span> <span class="badge bg-secondary">{{ leaverequests|length }}</span>
{% endif %} {% endif %}
</a> </a>
</li> </li>
{% endif %} {% endif %}
</a>
</li>
{% endif %}
<li class="nav-item "> <li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}" href="{% url 'groupmanagement:membership' %}">{% translate "Group Membership" %}</a> <a class="nav-link {% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}" href="{% url 'groupmanagement:membership' %}">{% translate "Group Membership" %}</a>
</li> </li>
@ -83,7 +91,50 @@
{% translate "Accept" %} {% translate "Accept" %}
</a> </a>
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger"> {% if not show_leave_tab %}
<div id="leave" class="tab-pane">
{% if leaverequests %}
<div class="table-responsive">
<table class="table table-aa">
<thead>
<tr>
<th>{% translate "Character" %}</th>
<th>{% translate "Organization" %}</th>
<th>{% translate "Group" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for leaverequest in leaverequests %}
<tr>
<td>
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;" alt="{{ leaverequest.main_char.character_name }}">
{% 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 %}
{% translate "(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">
{% translate "Accept" %}
</a>
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
{% translate "Reject" %} {% translate "Reject" %}
</a> </a>
</td> </td>
@ -92,6 +143,13 @@
</tbody> </tbody>
</table> </table>
</div> </div>
{% else %}
<div class="alert alert-warning text-center">{% translate "No group leave requests." %}</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
{% else %} {% else %}
<div class="alert alert-warning text-center">{% translate "No group add requests." %}</div> <div class="alert alert-warning text-center">{% translate "No group add requests." %}</div>
{% endif %} {% endif %}

View File

@ -6,22 +6,22 @@ from django.conf import settings
from django.contrib import admin 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 from django.contrib.auth.models import User
from django.test import TestCase, RequestFactory, Client, override_settings from django.test import Client, RequestFactory, TestCase, override_settings
from allianceauth.authentication.models import CharacterOwnership, State from allianceauth.authentication.models import CharacterOwnership, State
from allianceauth.eveonline.models import ( from allianceauth.eveonline.models import (
EveCharacter, EveCorporationInfo, EveAllianceInfo EveAllianceInfo, EveCharacter, EveCorporationInfo,
) )
from allianceauth.tests.auth_utils import AuthUtils from allianceauth.tests.auth_utils import AuthUtils
from . import get_admin_change_view_url from ..admin import Group, GroupAdmin, HasLeaderFilter
from ..admin import HasLeaderFilter, GroupAdmin, Group
from ..models import ReservedGroupName from ..models import ReservedGroupName
from . import get_admin_change_view_url
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS: if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
_has_auto_groups = True _has_auto_groups = True
from allianceauth.eveonline.autogroups.models import AutogroupsConfig from allianceauth.eveonline.autogroups.models import AutogroupsConfig
from ..admin import IsAutoGroupFilter from ..admin import IsAutoGroupFilter
else: else:
_has_auto_groups = False _has_auto_groups = False
@ -621,21 +621,16 @@ class TestGroupAdmin2(TestCase):
response = self.client.post( response = self.client.post(
f"/admin/groupmanagement/group/{group.pk}/change/", f"/admin/groupmanagement/group/{group.pk}/change/",
data={ data={
"name": f"{group.name}", "name": group.name,
"authgroup-TOTAL_FORMS": "1", "users": [user_member.pk, user_guest.pk],
"authgroup-INITIAL_FORMS": "1", "authgroup-TOTAL_FORMS": 1,
"authgroup-MIN_NUM_FORMS": "0", "authgroup-INITIAL_FORMS": 1,
"authgroup-MAX_NUM_FORMS": "1", "authgroup-MIN_NUM_FORMS": 0,
"authgroup-0-description": "", "authgroup-MAX_NUM_FORMS": 1,
"authgroup-0-states": f"{member_state.pk}", "authgroup-0-states": member_state.pk,
"authgroup-0-internal": "on", "authgroup-0-internal": "on",
"authgroup-0-hidden": "on", "authgroup-0-hidden": "on",
"authgroup-0-group": f"{group.pk}", "authgroup-0-group": group.pk,
"authgroup-__prefix__-description": "",
"authgroup-__prefix__-internal": "on",
"authgroup-__prefix__-hidden": "on",
"authgroup-__prefix__-group": f"{group.pk}",
"_save": "Save"
} }
) )
# then # then
@ -644,6 +639,85 @@ class TestGroupAdmin2(TestCase):
self.assertIn(group, user_member.groups.all()) self.assertIn(group, user_member.groups.all())
self.assertNotIn(group, user_guest.groups.all()) self.assertNotIn(group, user_guest.groups.all())
def test_should_add_user_to_existing_group(self):
# given
user_bruce = AuthUtils.create_user("Bruce Wayne")
user_lex = AuthUtils.create_user("Lex Luthor")
group = Group.objects.create(name="dummy")
user_bruce.groups.add(group)
self.client.force_login(self.superuser)
# when
response = self.client.post(
f"/admin/groupmanagement/group/{group.pk}/change/",
data={
"name": group.name,
"users": [user_bruce.pk, user_lex.pk],
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 1,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
"authgroup-0-internal": "on",
"authgroup-0-hidden": "on",
"authgroup-0-group": group.pk,
}
)
# then
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/admin/groupmanagement/group/")
self.assertIn(group, user_bruce.groups.all())
self.assertIn(group, user_lex.groups.all())
def test_should_remove_user_from_existing_group(self):
# given
user_bruce = AuthUtils.create_user("Bruce Wayne")
user_lex = AuthUtils.create_user("Lex Luthor")
group = Group.objects.create(name="dummy")
user_bruce.groups.add(group)
user_lex.groups.add(group)
self.client.force_login(self.superuser)
# when
response = self.client.post(
f"/admin/groupmanagement/group/{group.pk}/change/",
data={
"name": group.name,
"users": user_bruce.pk,
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 1,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
"authgroup-0-internal": "on",
"authgroup-0-hidden": "on",
"authgroup-0-group": group.pk,
}
)
# then
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/admin/groupmanagement/group/")
self.assertIn(group, user_bruce.groups.all())
self.assertNotIn(group, user_lex.groups.all())
def test_should_include_user_when_creating_group(self):
# given
user_bruce = AuthUtils.create_user("Bruce Wayne")
self.client.force_login(self.superuser)
# when
response = self.client.post(
"/admin/groupmanagement/group/add/",
data={
"name": "new group",
"users": user_bruce.pk,
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 0,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
}
)
# then
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/admin/groupmanagement/group/")
group = Group.objects.get(name="new group")
self.assertIn(group, user_bruce.groups.all())
class TestReservedGroupNameAdmin(TestCase): class TestReservedGroupNameAdmin(TestCase):
@classmethod @classmethod

View File

@ -1,6 +1,7 @@
from django.test import RequestFactory, TestCase, override_settings from django.test import RequestFactory, TestCase, override_settings
from django.urls import reverse from django.urls import reverse
from allianceauth.groupmanagement.models import Group, GroupRequest
from allianceauth.tests.auth_utils import AuthUtils from allianceauth.tests.auth_utils import AuthUtils
from .. import views from .. import views
@ -16,6 +17,7 @@ class TestViews(TestCase):
self.factory = RequestFactory() self.factory = RequestFactory()
self.user = AuthUtils.create_user('Peter Parker') self.user = AuthUtils.create_user('Peter Parker')
self.user_with_manage_permission = AuthUtils.create_user('Bruce Wayne') self.user_with_manage_permission = AuthUtils.create_user('Bruce Wayne')
self.group = Group.objects.create(name="Example group")
# set permissions # set permissions
AuthUtils.add_permission_to_user_by_name( AuthUtils.add_permission_to_user_by_name(
@ -83,3 +85,19 @@ class TestViews(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertNotIn('id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave"', content) self.assertNotIn('id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave"', content)
self.assertNotIn('<div id="leave" class="tab-pane">', content) self.assertNotIn('<div id="leave" class="tab-pane">', content)
@override_settings(GROUPMANAGEMENT_AUTO_LEAVE=True)
def test_should_not_hide_leave_requests_tab_when_there_are_open_requests(self):
# given
request = self.factory.get(reverse('groupmanagement:management'))
request.user = self.user_with_manage_permission
GroupRequest.objects.create(user=self.user, group=self.group, leave_request=True)
# when
response = views.group_management(request)
# then
content = response_content_to_str(response)
self.assertEqual(response.status_code, 200)
self.assertIn('<a data-toggle="tab" href="#leave">', content)
self.assertIn('<div id="leave" class="tab-pane">', content)

View File

@ -2,13 +2,12 @@ import logging
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db.models import Count from django.db.models import Count
from django.http import Http404 from django.http import Http404
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from allianceauth.notifications import notify from allianceauth.notifications import notify
@ -16,7 +15,6 @@ from allianceauth.notifications import notify
from .managers import GroupManager from .managers import GroupManager
from .models import GroupRequest, RequestLog from .models import GroupRequest, RequestLog
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -45,10 +43,15 @@ def group_management(request):
logger.debug("Providing user {} with {} acceptrequests and {} leaverequests.".format( logger.debug("Providing user {} with {} acceptrequests and {} leaverequests.".format(
request.user, len(acceptrequests), len(leaverequests))) request.user, len(acceptrequests), len(leaverequests)))
show_leave_tab = (
getattr(settings, 'GROUPMANAGEMENT_AUTO_LEAVE', False)
and not GroupRequest.objects.filter(leave_request=True).exists()
)
render_items = { render_items = {
'acceptrequests': acceptrequests, 'acceptrequests': acceptrequests,
'leaverequests': leaverequests, 'leaverequests': leaverequests,
'auto_leave': getattr(settings, 'GROUPMANAGEMENT_AUTO_LEAVE', False), 'show_leave_tab': show_leave_tab,
} }
return render(request, 'groupmanagement/index.html', context=render_items) return render(request, 'groupmanagement/index.html', context=render_items)

View File

@ -4,9 +4,9 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Erik Kalkoken <erik.kalkoken@gmail.com>, 2020 # Erik Kalkoken <erik.kalkoken@gmail.com>, 2023
# Joel Falknau <ozirascal@gmail.com>, 2021 # Joel Falknau <ozirascal@gmail.com>, 2023
# Peter Pfeufer, 2022 # Peter Pfeufer, 2023
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -14,8 +14,8 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Peter Pfeufer, 2022\n" "Last-Translator: Peter Pfeufer, 2023\n"
"Language-Team: German (https://app.transifex.com/alliance-auth/teams/107430/de/)\n" "Language-Team: German (https://app.transifex.com/alliance-auth/teams/107430/de/)\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"
@ -34,7 +34,8 @@ msgstr "Google Analytics V4"
#: allianceauth/authentication/decorators.py:37 #: allianceauth/authentication/decorators.py:37
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "" msgstr ""
"Für diese Aktion wird ein Hauptcharacter benötigt. Bitte füge einen hinzu." "Zur Ausführung dieser Aktion ist ein Hauptcharakter erforderlich. Füge unten"
" einen hinzu."
#: allianceauth/authentication/forms.py:12 #: allianceauth/authentication/forms.py:12
msgid "Email" msgid "Email"
@ -131,7 +132,7 @@ msgstr "Hauptcharakter ändern"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:125
msgid "Group Memberships" msgid "Group Memberships"
msgstr "Gruppen" msgstr "Gruppenmitgliedschaften"
#: allianceauth/authentication/templates/authentication/dashboard.html:145 #: allianceauth/authentication/templates/authentication/dashboard.html:145
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:21 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:21
@ -206,7 +207,7 @@ msgstr ""
#: allianceauth/authentication/views.py:83 #: allianceauth/authentication/views.py:83
#, python-format #, python-format
msgid "Changed main character to %(char)s" msgid "Changed main character to %(char)s"
msgstr "Haupcharakter geändert zu %(char)s" msgstr "Haupcharakter zu %(char)s geändert"
#: allianceauth/authentication/views.py:92 #: allianceauth/authentication/views.py:92
#, python-format #, python-format
@ -233,13 +234,12 @@ 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 ""
"Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur " "Bestätigungs-E-Mail gesendet. Bitte folge dem Link, um Deine E-Mail-Adresse "
"Bestätigung." "zu bestätigen."
#: allianceauth/authentication/views.py:257 #: allianceauth/authentication/views.py:257
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 einloggen zum Fortfahren."
"Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren."
#: allianceauth/authentication/views.py:262 #: allianceauth/authentication/views.py:262
msgid "Registration of new accounts is not allowed at this time." msgid "Registration of new accounts is not allowed at this time."
@ -274,7 +274,7 @@ msgstr "Hauptcharaktere"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:22 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:14 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:14
msgid "Members" msgid "Members"
msgstr "Mitgliederzahl" msgstr "Mitglieder"
#: allianceauth/corputils/templates/corputils/corpstats.html:35 #: allianceauth/corputils/templates/corputils/corpstats.html:35
msgid "Unregistered" msgid "Unregistered"
@ -282,7 +282,7 @@ msgstr "Nicht registriert"
#: allianceauth/corputils/templates/corputils/corpstats.html:38 #: allianceauth/corputils/templates/corputils/corpstats.html:38
msgid "Last update:" msgid "Last update:"
msgstr "Letzes Update:" msgstr "Letzte Aktualisierung:"
#: allianceauth/corputils/templates/corputils/corpstats.html:74 #: allianceauth/corputils/templates/corputils/corpstats.html:74
#: allianceauth/corputils/templates/corputils/corpstats.html:112 #: allianceauth/corputils/templates/corputils/corpstats.html:112
@ -382,11 +382,11 @@ msgstr "Charakter nicht registriert!"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
msgid "This character is not associated with an auth account." msgid "This character is not associated with an auth account."
msgstr "Dieser Charakter ist mit keinen Auth Konto verbunden." msgstr "Dieser Charakter ist keinem Auth Konto zugeordnet."
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
msgid "Add it here" msgid "Add it here"
msgstr "Füge es hier hinzu" msgstr "Füge ihn hier hinzu"
#: 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."
@ -394,7 +394,7 @@ msgstr "bevor Du versuchst auf FAT-Links zu klicken."
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:5 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:5
msgid "Create Fatlink" msgid "Create Fatlink"
msgstr "Erstelle FAT-Link" msgstr "FAT-Link erstellen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:9 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:9
#: allianceauth/optimer/templates/optimer/add.html:13 #: allianceauth/optimer/templates/optimer/add.html:13
@ -409,20 +409,20 @@ msgstr "Fehlerhafte Anfrage!"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:24 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:24
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:63 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:63
msgid "Create fatlink" msgid "Create fatlink"
msgstr "Erstelle FAT-Link" msgstr "FAT-Link erstellen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:3 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:3
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:4 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:4
msgid "Fatlink view" msgid "Fatlink view"
msgstr "FAT-Link sehen" msgstr "FAT-Link ansehen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:7 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:7
msgid "Edit fatlink" msgid "Edit fatlink"
msgstr "Editiere FAT-Link" msgstr "FAT-Link bearbeiten"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:11 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:11
msgid "Delete fat" msgid "Delete fat"
msgstr "Lösche FAT" msgstr "FAT löschen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:17 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:17
msgid "Registered characters" msgid "Registered characters"
@ -497,7 +497,7 @@ msgstr[1] "%(user)s hat diesen Monat %(links)s FAT-Links eingesammelt."
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html:26 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html:26
msgid "Times used" msgid "Times used"
msgstr "male genutzt" msgstr "Wie oft genutzt"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html:37 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html:37
#, python-format #, python-format
@ -570,7 +570,7 @@ msgstr "FAT-Link Statistik"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:20 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:20
msgid "Ticker" msgid "Ticker"
msgstr "Ticker: " msgstr "Ticker"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:8 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:8
msgid "Participation data" msgid "Participation data"
@ -594,7 +594,7 @@ msgstr "Letzter FAT-Link"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:58 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:58
msgid "View statistics" msgid "View statistics"
msgstr "Statistik" msgstr "Statistiken ansehen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:95 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:95
msgid "No created fatlinks on record." msgid "No created fatlinks on record."
@ -713,8 +713,8 @@ msgid ""
"States listed here will have the ability to join this group provided they " "States listed here will have the ability to join this group provided they "
"have the proper permissions.<br>" "have the proper permissions.<br>"
msgstr "" msgstr ""
"Hier gelistete Ränge können dieser Gruppe beitreten, vorausgesetzt sie haben" "Die hier aufgeführten Status können dieser Gruppe beitreten, sofern sie über"
" die entsprechenden Berechtigungen.<br>" " die entsprechenden Berechtigungen verfügen.<br>"
#: allianceauth/groupmanagement/models.py:171 #: allianceauth/groupmanagement/models.py:171
msgid "" msgid ""
@ -814,7 +814,7 @@ msgstr "Gruppenmitglieder"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:113 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:113
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:21 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:21
msgid "Organization" msgid "Organization"
msgstr "Organization" msgstr "Organisation"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:49 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:49
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:75 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:75
@ -933,18 +933,18 @@ msgstr "Gruppenverwaltung"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:24
msgid "Join Requests" msgid "Join Requests"
msgstr "Beitrittsgesuche" msgstr "Beitrittsanfragen"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:35 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:35
msgid "Leave Requests" msgid "Leave Requests"
msgstr "Austrittsgesuche" msgstr "Austrittsanfragen"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:57 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:57
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:114 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:114
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:18 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:18
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "Gruppen" msgstr "Gruppe"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:145 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:145
@ -968,7 +968,7 @@ msgstr "Keine Gruppenaustrittsanfragen"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:8 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:8
#: allianceauth/templates/allianceauth/top-menu.html:8 #: allianceauth/templates/allianceauth/top-menu.html:8
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "Toggle Navigation" msgstr "Navigation umschalten"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:19 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:19
msgid "Group Requests" msgid "Group Requests"
@ -994,7 +994,7 @@ msgstr "Gruppe existiert nicht"
#: allianceauth/groupmanagement/views.py:195 #: allianceauth/groupmanagement/views.py:195
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s zugestimmt." msgstr "Beitrittsanfrage von %(mainchar)s zur Gruppe %(group)s akzeptiert."
#: allianceauth/groupmanagement/views.py:201 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:232 #: allianceauth/groupmanagement/views.py:232
@ -1003,18 +1003,18 @@ msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s." "%(mainchar)s to %(group)s."
msgstr "" msgstr ""
"Bei der Bearbeitung des Beitrittsgesuchs von %(mainchar)s zur Gruppe " "Bei der Bearbeitung des Beitrittsanfrage von %(mainchar)s zur Gruppe "
"%(group)s ist ein unbehandelter Fehler aufgetreten." "%(group)s ist ein unbehandelter Fehler aufgetreten."
#: allianceauth/groupmanagement/views.py:226 #: allianceauth/groupmanagement/views.py:226
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s abgelehnt." msgstr "Beitrittsanfrage von %(mainchar)s zur Gruppe %(group)s abgelehnt."
#: allianceauth/groupmanagement/views.py:261 #: allianceauth/groupmanagement/views.py:261
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s akzeptiert." msgstr "Austrittsanfrage von %(mainchar)s für Gruppe %(group)s akzeptiert."
#: allianceauth/groupmanagement/views.py:266 #: allianceauth/groupmanagement/views.py:266
#: allianceauth/groupmanagement/views.py:298 #: allianceauth/groupmanagement/views.py:298
@ -1023,13 +1023,13 @@ msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
"Bei der Bearbeitung des Austrittsgesuchs von %(mainchar)s für Gruppe " "Bei der Bearbeitung des Austrittsanfrage von %(mainchar)s für Gruppe "
"%(group)s ist ein unbehandelter Fehler aufgetreten." "%(group)s ist ein unbehandelter Fehler aufgetreten."
#: allianceauth/groupmanagement/views.py:292 #: allianceauth/groupmanagement/views.py:292
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s abgelehnt." msgstr "Austrittsanfrage von %(mainchar)s für Gruppe %(group)s abgelehnt."
#: allianceauth/groupmanagement/views.py:336 #: allianceauth/groupmanagement/views.py:336
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:346
@ -1042,7 +1042,7 @@ msgstr "Du bist bereits Mitglied dieser Gruppe."
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:358
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "Du hast Dich bereits für diese Gruppe beworben." msgstr "Du hast bereits für diese Gruppe angefragt."
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:367
#, python-format #, python-format
@ -1059,12 +1059,12 @@ msgstr "Du bist kein Mitglied dieser Gruppe"
#: allianceauth/groupmanagement/views.py:393 #: allianceauth/groupmanagement/views.py:393
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "Du hast bereits ein ausstehendes Austrittsgesuch für diese Gruppe." msgstr "Du hast bereits eine ausstehendes Austrittsanfrage für diese Gruppe."
#: allianceauth/groupmanagement/views.py:409 #: allianceauth/groupmanagement/views.py:409
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "Austrittsgesuch für Gruppe %(group)s gesendet." msgstr "Austrittsanfrage für Gruppe %(group)s gesendet."
#: allianceauth/hrapplications/auth_hooks.py:14 #: allianceauth/hrapplications/auth_hooks.py:14
msgid "Applications" msgid "Applications"
@ -1086,11 +1086,11 @@ msgstr "Wähle eine Corporation"
#: allianceauth/hrapplications/templates/hrapplications/corpchoice.html:10 #: allianceauth/hrapplications/templates/hrapplications/corpchoice.html:10
msgid "Available Corps" msgid "Available Corps"
msgstr "Zur Auswahl stehende Corporations" msgstr "Verfügbare Corporationen"
#: allianceauth/hrapplications/templates/hrapplications/corpchoice.html:22 #: allianceauth/hrapplications/templates/hrapplications/corpchoice.html:22
msgid "No corps are accepting applications at this time." msgid "No corps are accepting applications at this time."
msgstr "Zur Zeit nimmt keine Corp Bewerbungen entgegen." msgstr "Zur Zeit nimmt keine Corp Bewerbungen an."
#: allianceauth/hrapplications/templates/hrapplications/create.html:4 #: allianceauth/hrapplications/templates/hrapplications/create.html:4
#: allianceauth/hrapplications/templates/hrapplications/create.html:7 #: allianceauth/hrapplications/templates/hrapplications/create.html:7
@ -1186,7 +1186,7 @@ msgstr "Keine angesehenen Bewerbungen"
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:62 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:62
#: allianceauth/hrapplications/templates/hrapplications/view.html:134 #: allianceauth/hrapplications/templates/hrapplications/view.html:134
msgid "Close" msgid "Close"
msgstr "Geschlossen" msgstr "Schließen"
#: allianceauth/hrapplications/templates/hrapplications/management.html:177 #: allianceauth/hrapplications/templates/hrapplications/management.html:177
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:63 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:63
@ -1200,7 +1200,7 @@ msgstr "Suche"
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:11 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:11
msgid "Application Search Results" msgid "Application Search Results"
msgstr "Bewerbungen Suchergebnisse" msgstr "Ergebnisse der Bewerbungssuche"
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:22 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:22
msgid "Application ID" msgid "Application ID"
@ -1342,12 +1342,12 @@ msgstr "Operationsart"
#: allianceauth/optimer/form.py:17 #: allianceauth/optimer/form.py:17
#: allianceauth/srp/templates/srp/management.html:38 #: allianceauth/srp/templates/srp/management.html:38
msgid "Fleet Commander" msgid "Fleet Commander"
msgstr "Flottenkommandeur" msgstr "Flottenkommandant"
#: allianceauth/optimer/form.py:22 allianceauth/srp/form.py:14 #: allianceauth/optimer/form.py:22 allianceauth/srp/form.py:14
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:91
msgid "Additional Info" msgid "Additional Info"
msgstr "Zusätzliche Info" msgstr "Zusätzliche Informationen"
#: allianceauth/optimer/form.py:23 #: allianceauth/optimer/form.py:23
msgid "(Optional) Describe the operation with a couple of short words." msgid "(Optional) Describe the operation with a couple of short words."
@ -1360,7 +1360,7 @@ msgstr "Operation erstellen"
#: allianceauth/optimer/templates/optimer/fleetoptable.html:12 #: allianceauth/optimer/templates/optimer/fleetoptable.html:12
msgid "Form Up System" msgid "Form Up System"
msgstr "Form Up System" msgstr "Startsystem"
#: allianceauth/optimer/templates/optimer/fleetoptable.html:14 #: allianceauth/optimer/templates/optimer/fleetoptable.html:14
#: allianceauth/timerboard/templates/timerboard/view.html:36 #: allianceauth/timerboard/templates/timerboard/view.html:36
@ -1384,20 +1384,20 @@ msgstr "Flottenoperationen Zeiten"
#: allianceauth/optimer/templates/optimer/management.html:20 #: allianceauth/optimer/templates/optimer/management.html:20
#: allianceauth/timerboard/templates/timerboard/view.html:22 #: allianceauth/timerboard/templates/timerboard/view.html:22
msgid "Current Eve Time:" msgid "Current Eve Time:"
msgstr "Momentane Eve Zeit" msgstr "Aktuelle Eve Zeit"
#: allianceauth/optimer/templates/optimer/management.html:26 #: allianceauth/optimer/templates/optimer/management.html:26
msgid "Next Fleet Operations" msgid "Next Fleet Operations"
msgstr "Anstehende Flottenoperationen" msgstr "Anstehende Flotten"
#: allianceauth/optimer/templates/optimer/management.html:30 #: allianceauth/optimer/templates/optimer/management.html:30
#: allianceauth/timerboard/templates/timerboard/view.html:362 #: allianceauth/timerboard/templates/timerboard/view.html:362
msgid "No upcoming timers." msgid "No upcoming timers."
msgstr "Keine kommenden Timer." msgstr "Keine bevorstehenden Timer."
#: allianceauth/optimer/templates/optimer/management.html:33 #: allianceauth/optimer/templates/optimer/management.html:33
msgid "Past Fleet Operations" msgid "Past Fleet Operations"
msgstr "Vergangene Flottenoperationen" msgstr "Vergangene Flotten"
#: allianceauth/optimer/templates/optimer/management.html:37 #: allianceauth/optimer/templates/optimer/management.html:37
#: allianceauth/timerboard/templates/timerboard/view.html:535 #: allianceauth/timerboard/templates/timerboard/view.html:535
@ -1408,7 +1408,7 @@ msgstr "Keine vergangenen Timer."
#: allianceauth/optimer/templates/optimer/update.html:15 #: allianceauth/optimer/templates/optimer/update.html:15
#: allianceauth/optimer/templates/optimer/update.html:27 #: allianceauth/optimer/templates/optimer/update.html:27
msgid "Update Fleet Operation" msgid "Update Fleet Operation"
msgstr "Aktualisiere Flottenoperationen" msgstr "Aktualisiere Flottenoperation"
#: allianceauth/optimer/templates/optimer/update.html:21 #: allianceauth/optimer/templates/optimer/update.html:21
msgid "Fleet Operation Does Not Exist" msgid "Fleet Operation Does Not Exist"
@ -1432,7 +1432,7 @@ msgstr "Änderungen für Operation timer %(opname)s gespeichert."
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:4 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:4
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:8 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:8
msgid "Permissions Audit" msgid "Permissions Audit"
msgstr "Berechtigungsübersicht" msgstr "Berechtigungsprüfung"
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
msgid "User / Character" msgid "User / Character"
@ -1494,11 +1494,11 @@ msgstr "Dienste"
#: allianceauth/services/forms.py:6 #: allianceauth/services/forms.py:6
msgid "Name of Fleet:" msgid "Name of Fleet:"
msgstr "SRP Flotte erstellen:" msgstr "Name der Flotte:"
#: allianceauth/services/forms.py:7 #: allianceauth/services/forms.py:7
msgid "Fleet Commander:" msgid "Fleet Commander:"
msgstr "Flottenkommandeur:" msgstr "Flottenkommandant:"
#: allianceauth/services/forms.py:8 #: allianceauth/services/forms.py:8
msgid "Fleet Comms:" msgid "Fleet Comms:"
@ -1514,11 +1514,11 @@ msgstr "Schiffspriorität:"
#: allianceauth/services/forms.py:11 #: allianceauth/services/forms.py:11
msgid "Formup Location:" msgid "Formup Location:"
msgstr "Formup Location:" msgstr "Startsystem:"
#: allianceauth/services/forms.py:12 #: allianceauth/services/forms.py:12
msgid "Formup Time:" msgid "Formup Time:"
msgstr "Formup Zeit:" msgstr "Startzeit:"
#: allianceauth/services/forms.py:13 #: allianceauth/services/forms.py:13
msgid "Expected Duration:" msgid "Expected Duration:"
@ -1530,7 +1530,7 @@ msgstr "Grund:"
#: allianceauth/services/forms.py:15 #: allianceauth/services/forms.py:15
msgid "Reimbursable?*" msgid "Reimbursable?*"
msgstr "Erstattungsfähig?" msgstr "Erstattungsfähig?*"
#: allianceauth/services/forms.py:15 allianceauth/services/forms.py:16 #: allianceauth/services/forms.py:15 allianceauth/services/forms.py:16
msgid "Yes" msgid "Yes"
@ -1542,7 +1542,7 @@ msgstr "Nein"
#: allianceauth/services/forms.py:16 #: allianceauth/services/forms.py:16
msgid "Important?*" msgid "Important?*"
msgstr "Wichtig?" msgstr "Wichtig?*"
#: allianceauth/services/forms.py:21 allianceauth/services/forms.py:31 #: allianceauth/services/forms.py:21 allianceauth/services/forms.py:31
msgid "Password" msgid "Password"
@ -1550,7 +1550,7 @@ msgstr "Passwort"
#: allianceauth/services/forms.py:26 allianceauth/services/forms.py:36 #: allianceauth/services/forms.py:26 allianceauth/services/forms.py:36
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "Passwort muss mindestens 8 Zeichen lang sein" msgstr "Das Passwort muss mindestens 8 Zeichen lang sein"
#: allianceauth/services/modules/discord/models.py:187 #: allianceauth/services/modules/discord/models.py:187
msgid "Discord Account Disabled" msgid "Discord Account Disabled"
@ -1591,7 +1591,7 @@ msgstr "Discord Konto deaktiviert."
#: allianceauth/services/modules/discord/views.py:36 #: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:59 #: allianceauth/services/modules/discord/views.py:59
msgid "An error occurred while processing your Discord account." msgid "An error occurred while processing your Discord account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Discord Kontos." msgstr "Es gab einen Fehler während der Verarbeitung Deines Discord Kontos."
#: allianceauth/services/modules/discord/views.py:102 #: allianceauth/services/modules/discord/views.py:102
msgid "Your Discord account has been successfully activated." msgid "Your Discord account has been successfully activated."
@ -1607,7 +1607,7 @@ msgstr ""
#: allianceauth/services/modules/discourse/views.py:29 #: allianceauth/services/modules/discourse/views.py:29
msgid "You are not authorized to access Discourse." msgid "You are not authorized to access Discourse."
msgstr "Du bist nicht autorisiert auf Discorse zuzugreifen." msgstr "Du bist nicht autorisiert auf Discourse zuzugreifen."
#: allianceauth/services/modules/discourse/views.py:34 #: allianceauth/services/modules/discourse/views.py:34
msgid "You must have a main character set to access Discourse." msgid "You must have a main character set to access Discourse."
@ -1619,14 +1619,14 @@ msgid ""
"No SSO payload or signature. Please contact support if this problem " "No SSO payload or signature. Please contact support if this problem "
"persists." "persists."
msgstr "" msgstr ""
"Keine SSO-Nutzdaten oder Signaturen. Bitte wenden Sie sich an den Support, " "Keine SSO-Nutzdaten oder Signaturen. Bitte wende Dich an den Support, wenn "
"wenn das Problem weiterhin besteht." "das Problem weiterhin besteht."
#: allianceauth/services/modules/discourse/views.py:54 #: allianceauth/services/modules/discourse/views.py:54
#: allianceauth/services/modules/discourse/views.py:62 #: allianceauth/services/modules/discourse/views.py:62
msgid "Invalid payload. Please contact support if this problem persists." msgid "Invalid payload. Please contact support if this problem persists."
msgstr "" msgstr ""
"Ungültige Nutzdaten. Bitte wenden Sie sich an den Support, wenn das Problem " "Ungültige Nutzdaten. Bitte wenden Dich an den Support, wenn das Problem "
"weiterhin besteht." "weiterhin besteht."
#: allianceauth/services/modules/ips4/views.py:31 #: allianceauth/services/modules/ips4/views.py:31
@ -1638,7 +1638,7 @@ msgstr "IP4Suite Konto aktiviert."
#: allianceauth/services/modules/ips4/views.py:81 #: allianceauth/services/modules/ips4/views.py:81
#: allianceauth/services/modules/ips4/views.py:101 #: allianceauth/services/modules/ips4/views.py:101
msgid "An error occurred while processing your IPSuite4 account." msgid "An error occurred while processing your IPSuite4 account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines IPSuite4 Kontos." msgstr "Es gab einen Fehler während der Verarbeitung Deines IPSuite4 Kontos."
#: allianceauth/services/modules/ips4/views.py:52 #: allianceauth/services/modules/ips4/views.py:52
msgid "Reset IPSuite4 password." msgid "Reset IPSuite4 password."
@ -1660,7 +1660,7 @@ msgstr "Jabber"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:5 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:5
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:10 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:10
msgid "Jabber Broadcast" msgid "Jabber Broadcast"
msgstr "Jabber Übertragung" msgstr "Jabber Ankündigung"
#: allianceauth/services/modules/openfire/auth_hooks.py:94 #: allianceauth/services/modules/openfire/auth_hooks.py:94
msgid "Fleet Broadcast Formatter" msgid "Fleet Broadcast Formatter"
@ -1672,11 +1672,11 @@ msgstr "Nachricht"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:16 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:16
msgid "Broadcast Sent!!" msgid "Broadcast Sent!!"
msgstr "Übertragung gesendet!!" msgstr "Ankündigung gesendet!!"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:22 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:22
msgid "Broadcast" msgid "Broadcast"
msgstr "Übertragungen" msgstr "Ankündigung"
#: allianceauth/services/modules/openfire/views.py:35 #: allianceauth/services/modules/openfire/views.py:35
msgid "Activated jabber account." msgid "Activated jabber account."
@ -1687,7 +1687,7 @@ msgstr "Jabber Konto aktiviert."
#: allianceauth/services/modules/openfire/views.py:76 #: allianceauth/services/modules/openfire/views.py:76
#: allianceauth/services/modules/openfire/views.py:147 #: allianceauth/services/modules/openfire/views.py:147
msgid "An error occurred while processing your jabber account." msgid "An error occurred while processing your jabber account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Jabber Kontos." msgstr "Es gab einen Fehler während der Verarbeitung Deines Jabber Kontos."
#: allianceauth/services/modules/openfire/views.py:69 #: allianceauth/services/modules/openfire/views.py:69
msgid "Reset jabber password." msgid "Reset jabber password."
@ -1696,7 +1696,7 @@ msgstr "Jabber Passwort zurücksetzen."
#: allianceauth/services/modules/openfire/views.py:115 #: allianceauth/services/modules/openfire/views.py:115
#, python-format #, python-format
msgid "Sent jabber broadcast to %s" msgid "Sent jabber broadcast to %s"
msgstr "Sende Jabber Durchsage an %s" msgstr "Sende Jabber Ankündigung an %s"
#: allianceauth/services/modules/openfire/views.py:144 #: allianceauth/services/modules/openfire/views.py:144
msgid "Set jabber password." msgid "Set jabber password."
@ -1711,7 +1711,7 @@ msgstr "Forum Konto aktiviert."
#: allianceauth/services/modules/phpbb3/views.py:78 #: allianceauth/services/modules/phpbb3/views.py:78
#: allianceauth/services/modules/phpbb3/views.py:101 #: allianceauth/services/modules/phpbb3/views.py:101
msgid "An error occurred while processing your forum account." msgid "An error occurred while processing your forum account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Forum Kontos." msgstr "Es gab einen Fehler während der Verarbeitung Deines Forum Kontos."
#: allianceauth/services/modules/phpbb3/views.py:53 #: allianceauth/services/modules/phpbb3/views.py:53
msgid "Deactivated forum account." msgid "Deactivated forum account."
@ -1734,7 +1734,7 @@ msgstr "SMF Konto aktiviert."
#: allianceauth/services/modules/smf/views.py:102 #: allianceauth/services/modules/smf/views.py:102
#: allianceauth/services/modules/smf/views.py:124 #: allianceauth/services/modules/smf/views.py:124
msgid "An error occurred while processing your SMF account." msgid "An error occurred while processing your SMF account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines SMF Kontos." msgstr "Es gab einen Fehler während der Verarbeitung Deines SMF Kontos."
#: allianceauth/services/modules/smf/views.py:78 #: allianceauth/services/modules/smf/views.py:78
msgid "Deactivated SMF account." msgid "Deactivated SMF account."
@ -1751,7 +1751,7 @@ msgstr "Setze SMF Passwort."
#: allianceauth/services/modules/teamspeak3/forms.py:14 #: allianceauth/services/modules/teamspeak3/forms.py:14
#, python-format #, python-format
msgid "Unable to locate user %s on server" msgid "Unable to locate user %s on server"
msgstr "Kann den Benutzer %s auf dem Server nicht finden" msgstr "Der Benutzer %s konnte auf dem Server nicht gefunden werden"
#: allianceauth/services/modules/teamspeak3/templates/admin/teamspeak3/authts/change_list.html:8 #: allianceauth/services/modules/teamspeak3/templates/admin/teamspeak3/authts/change_list.html:8
msgid "Update TS3 groups" msgid "Update TS3 groups"
@ -1783,7 +1783,8 @@ msgstr "TeamSpeak3 Konto aktiviert."
#: allianceauth/services/modules/teamspeak3/views.py:74 #: allianceauth/services/modules/teamspeak3/views.py:74
#: allianceauth/services/modules/teamspeak3/views.py:100 #: allianceauth/services/modules/teamspeak3/views.py:100
msgid "An error occurred while processing your TeamSpeak3 account." msgid "An error occurred while processing your TeamSpeak3 account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines TeamSpeak3 Kontos." msgstr ""
"Es gab einen Fehler während der Verarbeitung Deines TeamSpeak3 Kontos."
#: allianceauth/services/modules/teamspeak3/views.py:71 #: allianceauth/services/modules/teamspeak3/views.py:71
msgid "Deactivated TeamSpeak3 account." msgid "Deactivated TeamSpeak3 account."
@ -1802,7 +1803,7 @@ msgstr "XenForo Konto aktiviert."
#: allianceauth/services/modules/xenforo/views.py:73 #: allianceauth/services/modules/xenforo/views.py:73
#: allianceauth/services/modules/xenforo/views.py:94 #: allianceauth/services/modules/xenforo/views.py:94
msgid "An error occurred while processing your XenForo account." msgid "An error occurred while processing your XenForo account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines XenForo Kontos." msgstr "Es gab einen Fehler während der Verarbeitung Deines XenForo Kontos."
#: allianceauth/services/modules/xenforo/views.py:50 #: allianceauth/services/modules/xenforo/views.py:50
msgid "Deactivated XenForo account." msgid "Deactivated XenForo account."
@ -1832,7 +1833,7 @@ msgstr "Formatieren"
#: allianceauth/services/templates/services/service_confirm_delete.html:12 #: allianceauth/services/templates/services/service_confirm_delete.html:12
#, python-format #, python-format
msgid "Delete %(service_name)s Account?" msgid "Delete %(service_name)s Account?"
msgstr "Konto %(service_name)s löschen?" msgstr " %(service_name)s Konto löschen?"
#: allianceauth/services/templates/services/service_confirm_delete.html:20 #: allianceauth/services/templates/services/service_confirm_delete.html:20
#, python-format #, python-format
@ -1856,7 +1857,7 @@ msgstr "%(service_name)s Passwort ändern"
#: allianceauth/services/templates/services/service_password.html:9 #: allianceauth/services/templates/services/service_password.html:9
#, python-format #, python-format
msgid "Set %(service_name)s Password" msgid "Set %(service_name)s Password"
msgstr "%(service_name)s Passwort" msgstr "%(service_name)s Passwort setzen"
#: allianceauth/services/templates/services/service_password.html:17 #: allianceauth/services/templates/services/service_password.html:17
msgid "Set Password" msgid "Set Password"
@ -1927,7 +1928,7 @@ msgstr "SRP Flotten Daten"
#: allianceauth/srp/templates/srp/data.html:50 #: allianceauth/srp/templates/srp/data.html:50
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "SRP-Flotte Daten" msgstr "SRP Flotte Daten"
#: allianceauth/srp/templates/srp/data.html:55 #: allianceauth/srp/templates/srp/data.html:55
msgid "Mark Incomplete" msgid "Mark Incomplete"
@ -2005,7 +2006,7 @@ msgstr "Füge SRP Flotte hinzu"
#: allianceauth/srp/templates/srp/management.html:39 #: allianceauth/srp/templates/srp/management.html:39
msgid "Fleet AAR" msgid "Fleet AAR"
msgstr "Flotten AAR" msgstr "Flottenbericht"
#: allianceauth/srp/templates/srp/management.html:40 #: allianceauth/srp/templates/srp/management.html:40
msgid "Fleet SRP Code" msgid "Fleet SRP Code"
@ -2033,7 +2034,7 @@ msgstr "Deaktiviert"
#: allianceauth/srp/templates/srp/management.html:83 #: allianceauth/srp/templates/srp/management.html:83
msgid "Completed" msgid "Completed"
msgstr "Fertig" msgstr "Abgeschlossen"
#: allianceauth/srp/templates/srp/management.html:101 #: allianceauth/srp/templates/srp/management.html:101
msgid "Are you sure you want to delete this SRP code and its contents?" msgid "Are you sure you want to delete this SRP code and its contents?"
@ -2086,7 +2087,7 @@ msgstr "SRP Link für %(fleetname)s aktiviert."
#: allianceauth/srp/views.py:140 #: allianceauth/srp/views.py:140
#, python-format #, python-format
msgid "Marked SRP fleet %(fleetname)s as completed." msgid "Marked SRP fleet %(fleetname)s as completed."
msgstr "SRP Flotte %(fleetname)s als vollständig markiert." msgstr "SRP Flotte %(fleetname)s als abgeschlossen markiert."
#: allianceauth/srp/views.py:153 #: allianceauth/srp/views.py:153
#, python-format #, python-format
@ -2204,7 +2205,7 @@ msgstr "Testversion verfügbar"
#: allianceauth/templates/allianceauth/admin-status/overview.html:78 #: allianceauth/templates/allianceauth/admin-status/overview.html:78
msgid "Task Queue" msgid "Task Queue"
msgstr "Warteschlange" msgstr "Task-Warteschlange"
#: allianceauth/templates/allianceauth/admin-status/overview.html:81 #: allianceauth/templates/allianceauth/admin-status/overview.html:81
#, python-format #, python-format
@ -2249,7 +2250,7 @@ msgstr "Ausloggen"
#: allianceauth/timerboard/form.py:53 #: allianceauth/timerboard/form.py:53
msgid "Other" msgid "Other"
msgstr "anderes" msgstr "Anderes"
#: allianceauth/timerboard/form.py:54 #: allianceauth/timerboard/form.py:54
#: allianceauth/timerboard/templates/timerboard/view.html:62 #: allianceauth/timerboard/templates/timerboard/view.html:62
@ -2353,7 +2354,7 @@ msgstr "Timer löschen"
#: 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 "Bist Du sicher das Du Timer \"%(object)s\" löschen möchtest?" msgstr "Bist Du sicher das Du Timer „%(object)s“ löschen möchtest?"
#: 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

View File

@ -8,7 +8,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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2023-11-08 23:55+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -26,7 +26,7 @@ msgstr ""
msgid "Google Analytics V4" msgid "Google Analytics V4"
msgstr "" msgstr ""
#: allianceauth/authentication/decorators.py:37 #: allianceauth/authentication/decorators.py:49
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "" msgstr ""
@ -39,63 +39,68 @@ msgstr ""
msgid "You are not allowed to add or remove these restricted groups: %s" msgid "You are not allowed to add or remove these restricted groups: %s"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:80 #: allianceauth/authentication/models.py:71
msgid "English" msgid "English"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:81 #: allianceauth/authentication/models.py:72
msgid "German" msgid "German"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:82 #: allianceauth/authentication/models.py:73
msgid "Spanish" msgid "Spanish"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:83 #: allianceauth/authentication/models.py:74
msgid "Chinese Simplified" msgid "Chinese Simplified"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:84 #: allianceauth/authentication/models.py:75
msgid "Russian" msgid "Russian"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:85 #: allianceauth/authentication/models.py:76
msgid "Korean" msgid "Korean"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:86 #: allianceauth/authentication/models.py:77
msgid "French" msgid "French"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:87 #: allianceauth/authentication/models.py:78
msgid "Japanese" msgid "Japanese"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:88 #: allianceauth/authentication/models.py:79
msgid "Italian" msgid "Italian"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:91 #: allianceauth/authentication/models.py:80
msgid "Language" msgid "Ukrainian"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:96 #: allianceauth/authentication/models.py:96
msgid "Language"
msgstr ""
#: allianceauth/authentication/models.py:101
#: allianceauth/templates/allianceauth/night-toggle.html:6 #: allianceauth/templates/allianceauth/night-toggle.html:6
msgid "Night Mode" msgid "Night Mode"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:110 #: allianceauth/authentication/models.py:115
#, python-format #, python-format
msgid "State changed to: %s" msgid "State changed to: %s"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:111 #: allianceauth/authentication/models.py:116
#, python-format #, python-format
msgid "Your user's state is now: %(state)s" msgid "Your user's state is now: %(state)s"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:4 #: allianceauth/authentication/templates/authentication/dashboard.html:4
#: allianceauth/authentication/templates/authentication/dashboard.html:7 #: allianceauth/authentication/templates/authentication/dashboard.html:7
#: allianceauth/authentication/templates/authentication/tokens.html:4
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:10
msgid "Dashboard" msgid "Dashboard"
msgstr "" msgstr ""
@ -151,8 +156,49 @@ msgstr ""
msgid "Alliance" msgid "Alliance"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:7
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:62
msgid "Token Management"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:12
msgid "Scopes"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:13
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:127
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/hrapplications/templates/hrapplications/view.html:73
#: allianceauth/srp/templates/srp/data.html:101
#: allianceauth/srp/templates/srp/management.html:44
msgid "Actions"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:14
#: allianceauth/corputils/templates/corputils/corpstats.html:74
#: allianceauth/corputils/templates/corputils/corpstats.html:112
#: allianceauth/corputils/templates/corputils/corpstats.html:156
#: allianceauth/corputils/templates/corputils/search.html:13
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:22
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:26
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:55
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
msgid "Character"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:28
msgid ""
"This page is a best attempt, but backups or database logs can still contain "
"your tokens. Always revoke tokens on https://community.eveonline.com/support/"
"third-party-applications/ where possible."
msgstr ""
#: allianceauth/authentication/templates/public/login.html:6 #: allianceauth/authentication/templates/public/login.html:6
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:58 #: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:69
msgid "Login" msgid "Login"
msgstr "" msgstr ""
@ -184,47 +230,47 @@ msgstr ""
msgid "Invalid or expired activation link." msgid "Invalid or expired activation link."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:77 #: allianceauth/authentication/views.py:118
#, python-format #, python-format
msgid "" msgid ""
"Cannot change main character to %(char)s: character owned by a different " "Cannot change main character to %(char)s: character owned by a different "
"account." "account."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:83 #: allianceauth/authentication/views.py:124
#, python-format #, python-format
msgid "Changed main character to %(char)s" msgid "Changed main character to %(char)s"
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:92 #: allianceauth/authentication/views.py:133
#, python-format #, python-format
msgid "Added %(name)s to your account." msgid "Added %(name)s to your account."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:94 #: allianceauth/authentication/views.py:135
#, python-format #, python-format
msgid "Failed to add %(name)s to your account: they already have an account." msgid "Failed to add %(name)s to your account: they already have an account."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:133 #: allianceauth/authentication/views.py:174
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:197 #: allianceauth/authentication/views.py:238
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:252 #: allianceauth/authentication/views.py:296
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:257 #: allianceauth/authentication/views.py:301
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:262 #: allianceauth/authentication/views.py:306
msgid "Registration of new accounts is not allowed at this time." msgid "Registration of new accounts is not allowed at this time."
msgstr "" msgstr ""
@ -267,19 +313,6 @@ msgstr ""
msgid "Last update:" msgid "Last update:"
msgstr "" msgstr ""
#: allianceauth/corputils/templates/corputils/corpstats.html:74
#: allianceauth/corputils/templates/corputils/corpstats.html:112
#: allianceauth/corputils/templates/corputils/corpstats.html:156
#: allianceauth/corputils/templates/corputils/search.html:13
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:22
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:26
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:55
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
msgid "Character"
msgstr ""
#: allianceauth/corputils/templates/corputils/corpstats.html:75 #: allianceauth/corputils/templates/corputils/corpstats.html:75
#: allianceauth/corputils/templates/corputils/search.html:14 #: allianceauth/corputils/templates/corputils/search.html:14
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
@ -611,36 +644,41 @@ msgstr ""
msgid "Group Management" msgid "Group Management"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/forms.py:15 #: allianceauth/groupmanagement/forms.py:18
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:35
msgid "Users"
msgstr ""
#: allianceauth/groupmanagement/forms.py:52
msgid "This name has been reserved and can not be used for groups." msgid "This name has been reserved and can not be used for groups."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/forms.py:25 #: allianceauth/groupmanagement/forms.py:62
msgid "(auto)" msgid "(auto)"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/forms.py:34 #: allianceauth/groupmanagement/forms.py:71
msgid "There already exists a group with that name." msgid "There already exists a group with that name."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:105 #: allianceauth/groupmanagement/models.py:104
msgid "" msgid ""
"Internal group, users cannot see, join or request to join this group." "Internal group, users cannot see, join or request to join this group."
"<br>Used for groups such as Members, Corp_*, Alliance_* etc.<br><b>Overrides " "<br>Used for groups such as Members, Corp_*, Alliance_* etc.<br><b>Overrides "
"Hidden and Open options when selected.</b>" "Hidden and Open options when selected.</b>"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:113 #: allianceauth/groupmanagement/models.py:112
msgid "Group is hidden from users but can still join with the correct link." msgid "Group is hidden from users but can still join with the correct link."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:119 #: allianceauth/groupmanagement/models.py:118
msgid "" msgid ""
"Group is open and users will be automatically added upon request.<br>If the " "Group is open and users will be automatically added upon request.<br>If the "
"group is not open users will need their request manually approved." "group is not open users will need their request manually approved."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:126 #: allianceauth/groupmanagement/models.py:125
msgid "" msgid ""
"Group is public. Any registered user is able to join this group, with " "Group is public. Any registered user is able to join this group, with "
"visibility based on the other options set for this group.<br>Auth will not " "visibility based on the other options set for this group.<br>Auth will not "
@ -648,65 +686,65 @@ msgid ""
"authenticated." "authenticated."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:135 #: allianceauth/groupmanagement/models.py:134
msgid "" msgid ""
"Group is restricted. This means that adding or removing users for this group " "Group is restricted. This means that adding or removing users for this group "
"requires a superuser admin." "requires a superuser admin."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:144 #: allianceauth/groupmanagement/models.py:143
msgid "" msgid ""
"Group leaders can process requests for this group. Use the <code>auth." "Group leaders can process requests for this group. Use the <code>auth."
"group_management</code> permission to allow a user to manage all groups.<br>" "group_management</code> permission to allow a user to manage all groups.<br>"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:154 #: allianceauth/groupmanagement/models.py:153
msgid "" msgid ""
"Members of leader groups can process requests for this group. Use the " "Members of leader groups can process requests for this group. Use the "
"<code>auth.group_management</code> permission to allow a user to manage all " "<code>auth.group_management</code> permission to allow a user to manage all "
"groups.<br>" "groups.<br>"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:163 #: allianceauth/groupmanagement/models.py:162
msgid "" msgid ""
"States listed here will have the ability to join this group provided they " "States listed here will have the ability to join this group provided they "
"have the proper permissions.<br>" "have the proper permissions.<br>"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:171 #: allianceauth/groupmanagement/models.py:170
msgid "" msgid ""
"Short description <i>(max. 512 characters)</i> of the group shown to users." "Short description <i>(max. 512 characters)</i> of the group shown to users."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:178 #: allianceauth/groupmanagement/models.py:177
msgid "Can request non-public groups" msgid "Can request non-public groups"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:209 #: allianceauth/groupmanagement/models.py:208
msgid "name" msgid "name"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:212 #: allianceauth/groupmanagement/models.py:211
msgid "Name that can not be used for groups." msgid "Name that can not be used for groups."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:215 #: allianceauth/groupmanagement/models.py:214
msgid "reason" msgid "reason"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:215 #: allianceauth/groupmanagement/models.py:214
msgid "Reason why this name is reserved." msgid "Reason why this name is reserved."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:218 #: allianceauth/groupmanagement/models.py:217
msgid "created by" msgid "created by"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:223 #: allianceauth/groupmanagement/models.py:222
msgid "created at" msgid "created at"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/models.py:223 #: allianceauth/groupmanagement/models.py:222
msgid "Date when this entry was created" msgid "Date when this entry was created"
msgstr "" msgstr ""
@ -933,86 +971,86 @@ msgstr ""
msgid "Group Membership" msgid "Group Membership"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:163 #: allianceauth/groupmanagement/views.py:166
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:165 #: allianceauth/groupmanagement/views.py:168
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:168 #: allianceauth/groupmanagement/views.py:171
msgid "Group does not exist" msgid "Group does not exist"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:195 #: allianceauth/groupmanagement/views.py:198
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:201 #: allianceauth/groupmanagement/views.py:204
#: allianceauth/groupmanagement/views.py:232 #: allianceauth/groupmanagement/views.py:235
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s." "%(mainchar)s to %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:226 #: allianceauth/groupmanagement/views.py:229
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:261 #: allianceauth/groupmanagement/views.py:264
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:266 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:298 #: allianceauth/groupmanagement/views.py:301
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:292 #: allianceauth/groupmanagement/views.py:295
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:336 #: allianceauth/groupmanagement/views.py:339
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:349
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:341 #: allianceauth/groupmanagement/views.py:344
msgid "You are already a member of that group." msgid "You are already a member of that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:361
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:370
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:377 #: allianceauth/groupmanagement/views.py:380
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:381 #: allianceauth/groupmanagement/views.py:384
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:393 #: allianceauth/groupmanagement/views.py:396
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:409 #: allianceauth/groupmanagement/views.py:412
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "" msgstr ""
@ -1074,16 +1112,6 @@ msgstr ""
msgid "Username" msgid "Username"
msgstr "" msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:127
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/hrapplications/templates/hrapplications/view.html:73
#: allianceauth/srp/templates/srp/data.html:101
#: allianceauth/srp/templates/srp/management.html:44
msgid "Actions"
msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:38 #: allianceauth/hrapplications/templates/hrapplications/management.html:38
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:143 #: allianceauth/hrapplications/templates/hrapplications/management.html:143
@ -1422,10 +1450,6 @@ msgstr ""
msgid "Code Name" msgid "Code Name"
msgstr "" msgstr ""
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:35
msgid "Users"
msgstr ""
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:41 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:41
msgid "States" msgid "States"
msgstr "" msgstr ""
@ -2146,11 +2170,11 @@ msgid ""
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:95 #: allianceauth/templates/allianceauth/admin-status/overview.html:95
#, python-format msgid "running"
msgid "" msgstr ""
"\n"
" %(queue_length)s queued tasks\n" #: allianceauth/templates/allianceauth/admin-status/overview.html:96
" " msgid "queued"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/top-menu-admin.html:9 #: allianceauth/templates/allianceauth/top-menu-admin.html:9
@ -2166,11 +2190,11 @@ msgid "AA Support Discord"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:10 #: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:10
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:14 #: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:16
msgid "User Menu" msgid "User Menu"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:56 #: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:67
msgid "Logout" msgid "Logout"
msgstr "" msgstr ""
@ -2226,22 +2250,30 @@ msgid "Objective"
msgstr "" msgstr ""
#: allianceauth/timerboard/form.py:64 #: allianceauth/timerboard/form.py:64
msgid "Days Remaining" msgid "Absolute Timer"
msgstr "" msgstr ""
#: allianceauth/timerboard/form.py:65 #: allianceauth/timerboard/form.py:65
msgid "Hours Remaining" msgid "Date and Time"
msgstr ""
#: allianceauth/timerboard/form.py:66
msgid "Days Remaining"
msgstr "" msgstr ""
#: allianceauth/timerboard/form.py:67 #: allianceauth/timerboard/form.py:67
msgid "Minutes Remaining" msgid "Hours Remaining"
msgstr "" msgstr ""
#: allianceauth/timerboard/form.py:69 #: allianceauth/timerboard/form.py:69
msgid "Minutes Remaining"
msgstr ""
#: allianceauth/timerboard/form.py:71
msgid "Important" msgid "Important"
msgstr "" msgstr ""
#: allianceauth/timerboard/form.py:70 #: allianceauth/timerboard/form.py:72
msgid "Corp-Restricted" msgid "Corp-Restricted"
msgstr "" msgstr ""

View File

@ -4,11 +4,11 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# frank1210 <francolopez_16@hotmail.com>, 2021
# Joel Falknau <ozirascal@gmail.com>, 2021
# Young Anexo, 2023
# Fegpawn Kaundur, 2023 # Fegpawn Kaundur, 2023
# frank1210 <francolopez_16@hotmail.com>, 2023
# trenus, 2023 # trenus, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
# Young Anexo, 2023
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -16,8 +16,8 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: trenus, 2023\n" "Last-Translator: Young Anexo, 2023\n"
"Language-Team: Spanish (https://app.transifex.com/alliance-auth/teams/107430/es/)\n" "Language-Team: Spanish (https://app.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"

View File

@ -4,14 +4,14 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# François LACROIX-DURANT <umbre@fallenstarscreations.com>, 2020 # Keven D. <theenarki@gmail.com>, 2023
# Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2020 # rockclodbuster, 2023
# Keven D. <theenarki@gmail.com>, 2020 # Geoffrey Fabbro, 2023
# Idea ., 2021
# Mickael PATTE, 2021
# Geoffrey Fabbro, 2021
# Mohssine Daghghar, 2023 # Mohssine Daghghar, 2023
# Ludovick Fortin, 2023 # François LACROIX-DURANT <umbre@fallenstarscreations.com>, 2023
# Mickael PATTE, 2023
# Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2023
# Idea ., 2023
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -19,8 +19,8 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Ludovick Fortin, 2023\n" "Last-Translator: Idea ., 2023\n"
"Language-Team: French (France) (https://app.transifex.com/alliance-auth/teams/107430/fr_FR/)\n" "Language-Team: French (France) (https://app.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"

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,9 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Foch Petain <brigadier.rockforward@gmail.com>, 2020 # Foch Petain <brigadier.rockforward@gmail.com>, 2023
# kotaneko, 2023 # kotaneko, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -13,8 +14,8 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: kotaneko, 2023\n" "Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2023\n"
"Language-Team: Japanese (https://app.transifex.com/alliance-auth/teams/107430/ja/)\n" "Language-Team: Japanese (https://app.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"

View File

@ -4,13 +4,13 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# None None <khd1226543@gmail.com>, 2020 # None None <khd1226543@gmail.com>, 2023
# Seowon Jung <seowon@hawaii.edu>, 2020 # Joel Falknau <ozirascal@gmail.com>, 2023
# Olgeda Choi <undead.choi@gmail.com>, 2020 # Seowon Jung <seowon@hawaii.edu>, 2023
# Lahty <js03js70@gmail.com>, 2020 # Olgeda Choi <undead.choi@gmail.com>, 2023
# Joel Falknau <ozirascal@gmail.com>, 2020 # ThatRagingKid, 2023
# ThatRagingKid, 2022 # Lahty <js03js70@gmail.com>, 2023
# jackfrost, 2022 # jackfrost, 2023
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -18,8 +18,8 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: jackfrost, 2022\n" "Last-Translator: jackfrost, 2023\n"
"Language-Team: Korean (Korea) (https://app.transifex.com/alliance-auth/teams/107430/ko_KR/)\n" "Language-Team: Korean (Korea) (https://app.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"

View File

@ -4,9 +4,9 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Alexander Gess <de.alex.gess@gmail.com>, 2020 # Yuriy K <thedjcooltv@gmail.com>, 2023
# Yuriy K <thedjcooltv@gmail.com>, 2020 # Андрей Зубков <and.vareba81@gmail.com>, 2023
# Андрей Зубков <and.vareba81@gmail.com>, 2020 # Alexander Gess <de.alex.gess@gmail.com>, 2023
# Filipp Chertiev <f@fzfx.ru>, 2023 # Filipp Chertiev <f@fzfx.ru>, 2023
# #
#, fuzzy #, fuzzy
@ -15,7 +15,7 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Filipp Chertiev <f@fzfx.ru>, 2023\n" "Last-Translator: Filipp Chertiev <f@fzfx.ru>, 2023\n"
"Language-Team: Russian (https://app.transifex.com/alliance-auth/teams/107430/ru/)\n" "Language-Team: Russian (https://app.transifex.com/alliance-auth/teams/107430/ru/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"

View File

@ -4,6 +4,7 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Denys Ivchenko, 2023
# Kristof Swensen, 2023 # Kristof Swensen, 2023
# #
#, fuzzy #, fuzzy
@ -12,7 +13,7 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Kristof Swensen, 2023\n" "Last-Translator: Kristof Swensen, 2023\n"
"Language-Team: Ukrainian (https://app.transifex.com/alliance-auth/teams/107430/uk/)\n" "Language-Team: Ukrainian (https://app.transifex.com/alliance-auth/teams/107430/uk/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -32,7 +33,7 @@ msgstr "Google Analytics V4"
#: allianceauth/authentication/decorators.py:37 #: allianceauth/authentication/decorators.py:37
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "" msgstr ""
"Для виконання цієї дії потрібен головний персонаж. Додайте його нижче." "Для виконання цієї дії потрібен основний персонаж. Додайте його нижче."
#: allianceauth/authentication/forms.py:12 #: allianceauth/authentication/forms.py:12
msgid "Email" msgid "Email"
@ -124,7 +125,7 @@ msgstr "Додати персонажа"
#: allianceauth/authentication/templates/authentication/dashboard.html:115 #: allianceauth/authentication/templates/authentication/dashboard.html:115
msgid "Change Main" msgid "Change Main"
msgstr "Змінити головного персонажа" msgstr "Змінити основного персонажа"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:125
msgid "Group Memberships" msgid "Group Memberships"
@ -352,7 +353,7 @@ msgstr "Не вдалося зібрати статистику корпорац
#: allianceauth/fleetactivitytracking/auth_hooks.py:9 #: allianceauth/fleetactivitytracking/auth_hooks.py:9
msgid "Fleet Activity Tracking" msgid "Fleet Activity Tracking"
msgstr "Відстеження активності флоту" msgstr "Відстеження активності флотів"
#: allianceauth/fleetactivitytracking/forms.py:6 allianceauth/srp/form.py:8 #: allianceauth/fleetactivitytracking/forms.py:6 allianceauth/srp/form.py:8
#: allianceauth/srp/templates/srp/management.html:35 #: allianceauth/srp/templates/srp/management.html:35
@ -456,7 +457,7 @@ msgstr "Корабель"
#: allianceauth/timerboard/templates/timerboard/view.html:202 #: allianceauth/timerboard/templates/timerboard/view.html:202
#: allianceauth/timerboard/templates/timerboard/view.html:375 #: allianceauth/timerboard/templates/timerboard/view.html:375
msgid "Eve Time" msgid "Eve Time"
msgstr "Час в грі" msgstr "Ігровий час"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:33 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:33
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:36 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:36
@ -560,16 +561,16 @@ msgstr "Fats"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:4 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:4
msgid "Fatlink Corp Statistics" msgid "Fatlink Corp Statistics"
msgstr "Статистика корпорації Fatlink" msgstr "Статистика фатів корпорації"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:24 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:24
msgid "Average fats" msgid "Average fats"
msgstr "Середній показник fats" msgstr "Середній показник фатів"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:4 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:4
msgid "Fatlink statistics" msgid "Fatlink statistics"
msgstr "Статистика Fatlink" msgstr "Статистика фатів"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:20 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:20
msgid "Ticker" msgid "Ticker"
@ -625,7 +626,7 @@ msgid ""
"Cannot register the fleet participation for {character.character_name}. The " "Cannot register the fleet participation for {character.character_name}. The "
"character needs to be online." "character needs to be online."
msgstr "" msgstr ""
"Не можна зареєструвати участь в флоті для {character.character_name}. " "Не вдалося зареєструвати участь в флоті для {character.character_name}. "
"Персонаж повинен бути в мережі." "Персонаж повинен бути в мережі."
#: allianceauth/groupmanagement/auth_hooks.py:17 #: allianceauth/groupmanagement/auth_hooks.py:17
@ -659,8 +660,7 @@ msgstr ""
#: allianceauth/groupmanagement/models.py:113 #: allianceauth/groupmanagement/models.py:113
msgid "Group is hidden from users but can still join with the correct link." msgid "Group is hidden from users but can still join with the correct link."
msgstr "" msgstr ""
"Група прихована від користувачів, але можна приєднатися з правильним " "Група прихована від користувачів, але можна приєднатися за посиланням."
"посиланням."
#: allianceauth/groupmanagement/models.py:119 #: allianceauth/groupmanagement/models.py:119
msgid "" msgid ""
@ -1045,7 +1045,7 @@ msgstr "Ви вже є членом цієї групи."
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:358
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "У вас вже є очікуюча заявка на вступ до цієї групи." msgstr "Ви вже подали заявку на вступ до цієї групи."
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:367
#, python-format #, python-format
@ -1062,7 +1062,7 @@ msgstr "Ви не є учасником цієї групи"
#: allianceauth/groupmanagement/views.py:393 #: allianceauth/groupmanagement/views.py:393
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "Ви вже маєте очікувану запит на вихід з цієї групи." msgstr "Ви вже подали запит на вихід з цієї групи."
#: allianceauth/groupmanagement/views.py:409 #: allianceauth/groupmanagement/views.py:409
#, python-format #, python-format
@ -1321,7 +1321,7 @@ msgstr "Всі прочитані повідомлення видалено."
#: allianceauth/optimer/auth_hooks.py:10 #: allianceauth/optimer/auth_hooks.py:10
msgid "Fleet Operations" msgid "Fleet Operations"
msgstr "Операції флоту" msgstr "Флотові операції"
#: allianceauth/optimer/form.py:12 #: allianceauth/optimer/form.py:12
#: allianceauth/optimer/templates/optimer/fleetoptable.html:11 #: allianceauth/optimer/templates/optimer/fleetoptable.html:11
@ -1345,7 +1345,7 @@ msgstr "Тип операції"
#: allianceauth/optimer/form.py:17 #: allianceauth/optimer/form.py:17
#: allianceauth/srp/templates/srp/management.html:38 #: allianceauth/srp/templates/srp/management.html:38
msgid "Fleet Commander" msgid "Fleet Commander"
msgstr "Командувач флоту" msgstr "Командир флоту"
#: allianceauth/optimer/form.py:22 allianceauth/srp/form.py:14 #: allianceauth/optimer/form.py:22 allianceauth/srp/form.py:14
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:91
@ -1400,7 +1400,7 @@ msgstr "Немає наступних таймерів."
#: allianceauth/optimer/templates/optimer/management.html:33 #: allianceauth/optimer/templates/optimer/management.html:33
msgid "Past Fleet Operations" msgid "Past Fleet Operations"
msgstr "Минулі флотові операції" msgstr "Завершені флотові операції"
#: allianceauth/optimer/templates/optimer/management.html:37 #: allianceauth/optimer/templates/optimer/management.html:37
#: allianceauth/timerboard/templates/timerboard/view.html:535 #: allianceauth/timerboard/templates/timerboard/view.html:535
@ -1484,7 +1484,7 @@ msgstr "Стани"
#: allianceauth/services/abstract.py:72 #: allianceauth/services/abstract.py:72
msgid "That service account already exists" msgid "That service account already exists"
msgstr "Такий обліковий запис сервісу вже існує" msgstr "Такий сервісний обліковий запис вже існує"
#: allianceauth/services/abstract.py:103 #: allianceauth/services/abstract.py:103
#, python-brace-format #, python-brace-format
@ -1505,7 +1505,7 @@ msgstr "Командир флоту:"
#: allianceauth/services/forms.py:8 #: allianceauth/services/forms.py:8
msgid "Fleet Comms:" msgid "Fleet Comms:"
msgstr "Комунікації флоту:" msgstr "Голосовий канал флоту:"
#: allianceauth/services/forms.py:9 #: allianceauth/services/forms.py:9
msgid "Fleet Type:" msgid "Fleet Type:"
@ -1545,7 +1545,7 @@ msgstr "Ні"
#: allianceauth/services/forms.py:16 #: allianceauth/services/forms.py:16
msgid "Important?*" msgid "Important?*"
msgstr "Важливо?*" msgstr "Важливий?*"
#: allianceauth/services/forms.py:21 allianceauth/services/forms.py:31 #: allianceauth/services/forms.py:21 allianceauth/services/forms.py:31
msgid "Password" msgid "Password"
@ -1614,7 +1614,7 @@ msgstr "Ви не маєте прав на доступ до Discourse."
#: allianceauth/services/modules/discourse/views.py:34 #: allianceauth/services/modules/discourse/views.py:34
msgid "You must have a main character set to access Discourse." msgid "You must have a main character set to access Discourse."
msgstr "Ви повинні мати головний персонаж, щоб отримати доступ до Discourse." msgstr "Ви повинні мати основний персонаж, щоб отримати доступ до Discourse."
#: allianceauth/services/modules/discourse/views.py:44 #: allianceauth/services/modules/discourse/views.py:44
msgid "" msgid ""
@ -1702,7 +1702,7 @@ msgstr "Відправлено трансляцію Jabber на %s"
#: allianceauth/services/modules/openfire/views.py:144 #: allianceauth/services/modules/openfire/views.py:144
msgid "Set jabber password." msgid "Set jabber password."
msgstr "Встановлення пароля Jabber." msgstr "Встановити пароль Jabber."
#: allianceauth/services/modules/phpbb3/views.py:34 #: allianceauth/services/modules/phpbb3/views.py:34
msgid "Activated forum account." msgid "Activated forum account."
@ -1713,7 +1713,7 @@ msgstr "Активований обліковий запис форуму."
#: allianceauth/services/modules/phpbb3/views.py:78 #: allianceauth/services/modules/phpbb3/views.py:78
#: allianceauth/services/modules/phpbb3/views.py:101 #: allianceauth/services/modules/phpbb3/views.py:101
msgid "An error occurred while processing your forum account." msgid "An error occurred while processing your forum account."
msgstr "Виникла помилка під час обробки вашого облікового запису форуму." msgstr "Виникла помилка під час обробки вашого облікового запису на форумі."
#: allianceauth/services/modules/phpbb3/views.py:53 #: allianceauth/services/modules/phpbb3/views.py:53
msgid "Deactivated forum account." msgid "Deactivated forum account."
@ -1721,11 +1721,11 @@ msgstr "Деактивований обліковий запис форуму."
#: allianceauth/services/modules/phpbb3/views.py:70 #: allianceauth/services/modules/phpbb3/views.py:70
msgid "Reset forum password." msgid "Reset forum password."
msgstr "Скидання пароля форуму." msgstr "Скинути пароль форуму."
#: allianceauth/services/modules/phpbb3/views.py:98 #: allianceauth/services/modules/phpbb3/views.py:98
msgid "Set forum password." msgid "Set forum password."
msgstr "Встановлення пароля форуму." msgstr "Встановити пароль форуму."
#: allianceauth/services/modules/smf/views.py:52 #: allianceauth/services/modules/smf/views.py:52
msgid "Activated SMF account." msgid "Activated SMF account."
@ -1744,11 +1744,11 @@ msgstr "Деактивований обліковий запис SMF."
#: allianceauth/services/modules/smf/views.py:95 #: allianceauth/services/modules/smf/views.py:95
msgid "Reset SMF password." msgid "Reset SMF password."
msgstr "Скидання пароля SMF." msgstr "Скинути пароль SMF."
#: allianceauth/services/modules/smf/views.py:121 #: allianceauth/services/modules/smf/views.py:121
msgid "Set SMF password." msgid "Set SMF password."
msgstr "Встановлення пароля SMF." msgstr "Встановити пароль SMF."
#: allianceauth/services/modules/teamspeak3/forms.py:14 #: allianceauth/services/modules/teamspeak3/forms.py:14
#, python-format #, python-format
@ -1761,7 +1761,7 @@ msgstr "Оновити групи TS3"
#: allianceauth/services/modules/teamspeak3/templates/services/teamspeak3/teamspeakjoin.html:5 #: allianceauth/services/modules/teamspeak3/templates/services/teamspeak3/teamspeakjoin.html:5
msgid "Verify Teamspeak" msgid "Verify Teamspeak"
msgstr "Перевірте Teamspeak" msgstr "Перевірити Teamspeak"
#: allianceauth/services/modules/teamspeak3/templates/services/teamspeak3/teamspeakjoin.html:10 #: allianceauth/services/modules/teamspeak3/templates/services/teamspeak3/teamspeakjoin.html:10
msgid "Verify Teamspeak Identity" msgid "Verify Teamspeak Identity"
@ -1869,11 +1869,11 @@ msgstr "Керування послугами"
#: allianceauth/services/templates/services/services.html:9 #: allianceauth/services/templates/services/services.html:9
msgid "Available Services" msgid "Available Services"
msgstr "Доступні послуги" msgstr "Доступні сервіси"
#: allianceauth/services/templates/services/services.html:14 #: allianceauth/services/templates/services/services.html:14
msgid "Service" msgid "Service"
msgstr "Послуга" msgstr "Сервіс"
#: allianceauth/services/templates/services/services.html:16 #: allianceauth/services/templates/services/services.html:16
msgid "Domain" msgid "Domain"
@ -1881,7 +1881,7 @@ msgstr "Домен"
#: allianceauth/srp/auth_hooks.py:13 #: allianceauth/srp/auth_hooks.py:13
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "Компенсація за корабель" msgstr "Компенсації"
#: allianceauth/srp/form.py:9 #: allianceauth/srp/form.py:9
#: allianceauth/srp/templates/srp/management.html:36 #: allianceauth/srp/templates/srp/management.html:36

View File

@ -4,9 +4,10 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Joel Falknau <ozirascal@gmail.com>, 2020 # Jesse . <sgeine@hotmail.com>, 2023
# Jesse . <sgeine@hotmail.com>, 2020 # Aaron BuBu <351793078@qq.com>, 2023
# Aaron BuBu <351793078@qq.com>, 2020 # Joel Falknau <ozirascal@gmail.com>, 2023
# Shen Yang, 2023
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -14,8 +15,8 @@ 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: 2022-10-09 18:20+1000\n" "POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Aaron BuBu <351793078@qq.com>, 2020\n" "Last-Translator: Shen Yang, 2023\n"
"Language-Team: Chinese Simplified (https://app.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n" "Language-Team: Chinese Simplified (https://app.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"
@ -46,48 +47,48 @@ msgstr ""
#: allianceauth/authentication/models.py:80 #: allianceauth/authentication/models.py:80
msgid "English" msgid "English"
msgstr "" msgstr "英语"
#: allianceauth/authentication/models.py:81 #: allianceauth/authentication/models.py:81
msgid "German" msgid "German"
msgstr "" msgstr "德语"
#: allianceauth/authentication/models.py:82 #: allianceauth/authentication/models.py:82
msgid "Spanish" msgid "Spanish"
msgstr "" msgstr "西班牙语"
#: allianceauth/authentication/models.py:83 #: allianceauth/authentication/models.py:83
msgid "Chinese Simplified" msgid "Chinese Simplified"
msgstr "" msgstr "简体中文"
#: allianceauth/authentication/models.py:84 #: allianceauth/authentication/models.py:84
msgid "Russian" msgid "Russian"
msgstr "" msgstr "俄语"
#: allianceauth/authentication/models.py:85 #: allianceauth/authentication/models.py:85
msgid "Korean" msgid "Korean"
msgstr "" msgstr "韩语"
#: allianceauth/authentication/models.py:86 #: allianceauth/authentication/models.py:86
msgid "French" msgid "French"
msgstr "" msgstr "法语"
#: allianceauth/authentication/models.py:87 #: allianceauth/authentication/models.py:87
msgid "Japanese" msgid "Japanese"
msgstr "" msgstr "日语"
#: allianceauth/authentication/models.py:88 #: allianceauth/authentication/models.py:88
msgid "Italian" msgid "Italian"
msgstr "" msgstr "意大利语"
#: allianceauth/authentication/models.py:91 #: allianceauth/authentication/models.py:91
msgid "Language" msgid "Language"
msgstr "" msgstr "语言"
#: allianceauth/authentication/models.py:96 #: allianceauth/authentication/models.py:96
#: allianceauth/templates/allianceauth/night-toggle.html:6 #: allianceauth/templates/allianceauth/night-toggle.html:6
msgid "Night Mode" msgid "Night Mode"
msgstr "" msgstr "夜间模式"
#: allianceauth/authentication/models.py:110 #: allianceauth/authentication/models.py:110
#, python-format #, python-format
@ -696,7 +697,7 @@ msgstr ""
#: allianceauth/groupmanagement/models.py:215 #: allianceauth/groupmanagement/models.py:215
msgid "reason" msgid "reason"
msgstr "" msgstr "原因"
#: allianceauth/groupmanagement/models.py:215 #: allianceauth/groupmanagement/models.py:215
msgid "Reason why this name is reserved." msgid "Reason why this name is reserved."
@ -754,7 +755,7 @@ msgstr "操作者"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:48 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:48
msgid "Removed" msgid "Removed"
msgstr "" msgstr "已移除"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:60 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:60
msgid "All times displayed are EVE/UTC." msgid "All times displayed are EVE/UTC."
@ -1198,11 +1199,11 @@ msgstr "添加评论"
#: allianceauth/notifications/models.py:21 #: allianceauth/notifications/models.py:21
msgid "danger" msgid "danger"
msgstr "" msgstr "危险"
#: allianceauth/notifications/models.py:22 #: allianceauth/notifications/models.py:22
msgid "warning" msgid "warning"
msgstr "" msgstr "警告"
#: allianceauth/notifications/models.py:23 #: allianceauth/notifications/models.py:23
msgid "info" msgid "info"
@ -1343,7 +1344,7 @@ msgstr "当前EVE游戏内时间"
#: allianceauth/optimer/templates/optimer/management.html:26 #: allianceauth/optimer/templates/optimer/management.html:26
msgid "Next Fleet Operations" msgid "Next Fleet Operations"
msgstr "" msgstr "下一个舰队任务"
#: allianceauth/optimer/templates/optimer/management.html:30 #: allianceauth/optimer/templates/optimer/management.html:30
#: allianceauth/timerboard/templates/timerboard/view.html:362 #: allianceauth/timerboard/templates/timerboard/view.html:362
@ -1352,7 +1353,7 @@ msgstr "没有快到的时间节点,歇一会吧"
#: allianceauth/optimer/templates/optimer/management.html:33 #: allianceauth/optimer/templates/optimer/management.html:33
msgid "Past Fleet Operations" msgid "Past Fleet Operations"
msgstr "" msgstr "过去的舰队任务"
#: allianceauth/optimer/templates/optimer/management.html:37 #: allianceauth/optimer/templates/optimer/management.html:37
#: allianceauth/timerboard/templates/timerboard/view.html:535 #: allianceauth/timerboard/templates/timerboard/view.html:535
@ -2257,15 +2258,15 @@ msgstr ""
#: allianceauth/timerboard/models.py:15 #: allianceauth/timerboard/models.py:15
msgid "Shield" msgid "Shield"
msgstr "" msgstr "护盾"
#: allianceauth/timerboard/models.py:16 #: allianceauth/timerboard/models.py:16
msgid "Armor" msgid "Armor"
msgstr "" msgstr "装甲"
#: allianceauth/timerboard/models.py:17 #: allianceauth/timerboard/models.py:17
msgid "Hull" msgid "Hull"
msgstr "" msgstr "结构"
#: allianceauth/timerboard/models.py:18 #: allianceauth/timerboard/models.py:18
msgid "Final" msgid "Final"
@ -2273,11 +2274,11 @@ msgstr ""
#: allianceauth/timerboard/models.py:19 #: allianceauth/timerboard/models.py:19
msgid "Anchoring" msgid "Anchoring"
msgstr "" msgstr "铆钉"
#: allianceauth/timerboard/models.py:20 #: allianceauth/timerboard/models.py:20
msgid "Unanchoring" msgid "Unanchoring"
msgstr "" msgstr "解锚"
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:11 #: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:11
msgid "Delete Timer" msgid "Delete Timer"

View File

@ -11,6 +11,9 @@ from .models import DiscordUser
from .urls import urlpatterns from .urls import urlpatterns
from .utils import LoggerAddTag from .utils import LoggerAddTag
from . import tasks, __title__ from . import tasks, __title__
from .app_settings import (
DISCORD_SYNC_NAMES
)
logger = LoggerAddTag(logging.getLogger(__name__), __title__) logger = LoggerAddTag(logging.getLogger(__name__), __title__)
@ -98,6 +101,7 @@ class DiscordService(ServicesHook):
return has_perms return has_perms
def sync_nickname(self, user): def sync_nickname(self, user):
if DISCORD_SYNC_NAMES:
logger.debug('Syncing %s nickname for user %s', self.name, user) logger.debug('Syncing %s nickname for user %s', self.name, user)
if self.user_has_account(user): if self.user_has_account(user):
tasks.update_nickname.apply_async( tasks.update_nickname.apply_async(

View File

@ -81,11 +81,18 @@ class TestDiscordService(NoSocketsTestCase):
self.assertFalse(DiscordUser.objects.filter(user=self.none_member).exists()) self.assertFalse(DiscordUser.objects.filter(user=self.none_member).exists())
@patch(MODULE_PATH + '.tasks.update_nickname') @patch(MODULE_PATH + '.tasks.update_nickname')
@patch(MODULE_PATH + '.auth_hooks.DISCORD_SYNC_NAMES', True)
def test_sync_nickname(self, mock_update_nickname): def test_sync_nickname(self, mock_update_nickname):
service = self.service() service = self.service()
service.sync_nickname(self.member) service.sync_nickname(self.member)
self.assertTrue(mock_update_nickname.apply_async.called) self.assertTrue(mock_update_nickname.apply_async.called)
@patch(MODULE_PATH + '.tasks.update_nickname')
def test_sync_nickname_no_setting(self, mock_update_nickname):
service = self.service()
service.sync_nickname(self.member)
self.assertFalse(mock_update_nickname.apply_async.called)
@patch(MODULE_PATH + '.tasks.update_nicknames_bulk') @patch(MODULE_PATH + '.tasks.update_nicknames_bulk')
def test_sync_nicknames_bulk(self, mock_update_nicknames_bulk): def test_sync_nicknames_bulk(self, mock_update_nicknames_bulk):
service = self.service() service = self.service()

View File

@ -164,6 +164,7 @@ class TestServiceFeatures(TransactionTestCase):
self.discord_user = DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID) self.discord_user = DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
self.assertTrue(DiscordUser.objects.user_has_account(self.user)) self.assertTrue(DiscordUser.objects.user_has_account(self.user))
@patch(MODULE_PATH + '.auth_hooks.DISCORD_SYNC_NAMES', True)
def test_when_name_of_main_changes_then_discord_nick_is_updated( def test_when_name_of_main_changes_then_discord_nick_is_updated(
self, requests_mocker self, requests_mocker
): ):
@ -185,6 +186,7 @@ class TestServiceFeatures(TransactionTestCase):
self.assertTrue(nick_updated) self.assertTrue(nick_updated)
self.assertTrue(DiscordUser.objects.user_has_account(self.user)) self.assertTrue(DiscordUser.objects.user_has_account(self.user))
@patch(MODULE_PATH + '.auth_hooks.DISCORD_SYNC_NAMES', True)
def test_when_name_of_main_changes_and_user_deleted_then_account_is_deleted( def test_when_name_of_main_changes_and_user_deleted_then_account_is_deleted(
self, requests_mocker self, requests_mocker
): ):

72
docs/_static/css/tabs.css vendored Normal file
View File

@ -0,0 +1,72 @@
.sphinx-tabs {
margin-bottom: 1rem;
}
[role="tablist"] {
border-bottom: 1px solid #a0b3bf;
}
.sphinx-tabs-tab {
position: relative;
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif;
color: #1D5C87;
line-height: 24px;
margin: 0;
font-size: 16px;
font-weight: 400;
background-color: rgba(255, 255, 255, 0);
border-radius: 5px 5px 0 0;
border: 0;
padding: 1rem 1.5rem;
margin-bottom: 0;
}
.sphinx-tabs-tab[aria-selected="true"] {
font-weight: 700;
border: 1px solid #a0b3bf;
border-bottom: 1px solid white;
margin: -1px;
background-color: white;
}
.sphinx-tabs-tab:focus {
z-index: 1;
outline-offset: 1px;
}
.sphinx-tabs-panel {
position: relative;
padding: 1rem;
border: 1px solid #a0b3bf;
margin: 0px -1px -1px -1px;
border-radius: 0 0 5px 5px;
border-top: 0;
background: white;
}
.sphinx-tabs-panel.code-tab {
padding: 0.4rem;
}
.sphinx-tab img {
margin-bottom: 24 px;
}
/* Dark theme preference styling */
@media (prefers-color-scheme: dark) {
.sphinx-tabs-panel {
color: white;
background-color: rgb(50, 50, 50);
}
.sphinx-tabs-tab {
color: white;
background-color: rgba(255, 255, 255, 0.05);
}
.sphinx-tabs-tab[aria-selected="true"] {
border-bottom: 1px solid rgb(50, 50, 50);
background-color: rgb(50, 50, 50);
}
}

View File

@ -1,15 +1,10 @@
# Configuration file for the Sphinx documentation builder.
# #
# Alliance Auth documentation build configuration file, created by # This file only contains a selection of the most common options. For a full
# sphinx-quickstart on Tue Jan 3 12:56:59 2017. # list see the documentation:
# # https://www.sphinx-doc.org/en/master/usage/configuration.html
# This file is execfile()d with the current directory set to its
# containing dir. # -- Path setup --------------------------------------------------------------
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
@ -18,23 +13,23 @@
import os import os
import sys import sys
import django import django
import sphinx_rtd_theme # noqa
sys.path.insert(0, os.path.abspath('..')) sys.path.insert(0, os.path.abspath('..'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings_all' os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings_all'
django.setup() django.setup()
# -- Project information -----------------------------------------------------
project = 'Alliance Auth'
copyright = '2018-2023, Alliance Auth'
author = 'Alliance Auth Team'
# -- General configuration ---------------------------------------------------
# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org # on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True' on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
# Support for recommonmark module
import recommonmark
from recommonmark.transform import AutoStructify
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
@ -42,11 +37,18 @@ from recommonmark.transform import AutoStructify
extensions = [ extensions = [
'sphinx_rtd_theme', 'sphinx_rtd_theme',
'sphinx.ext.autodoc', 'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon', 'sphinx.ext.napoleon',
'recommonmark',
'sphinxcontrib_django2',
'sphinx.ext.viewcode', 'sphinx.ext.viewcode',
'sphinx_copybutton' 'myst_parser',
'sphinxcontrib_django',
'sphinx_copybutton',
'sphinx_tabs.tabs'
]
myst_enable_extensions = [
"colon_fence",
"tasklist",
] ]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
@ -59,41 +61,16 @@ templates_path = ['_templates']
source_suffix = ['.md', '.rst'] source_suffix = ['.md', '.rst']
# The master toctree document. # The master toctree document.
master_doc = 'index' root_doc = 'index'
# General information about the project.
project = 'Alliance Auth'
copyright = '2018-2022, Alliance Auth'
author = 'Alliance Auth Team'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '3.0'
# The full version, including alpha/beta/rc tags.
# release = u'1.14.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path # This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing. # If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False todo_include_todos = False
# -- Options for HTML output ---------------------------------------------- # -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
@ -101,20 +78,11 @@ todo_include_todos = False
# #
html_theme = 'sphinx_rtd_theme' html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
'navigation_depth': 4,
}
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ['_static']
html_css_files = ["css/rtd_dark.css"] html_css_files = ["css/rtd_dark.css", "css/tabs.css"]
# -- Options for HTMLHelp output ------------------------------------------ # -- Options for HTMLHelp output ------------------------------------------
@ -147,7 +115,7 @@ latex_elements = {
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
(master_doc, 'AllianceAuth.tex', 'Alliance Auth Documentation', 'R4stl1n', 'manual'), (root_doc, 'AllianceAuth.tex', 'Alliance Auth Documentation', 'Alliance Auth Team', 'manual'),
] ]
@ -156,7 +124,7 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
(master_doc, 'allianceauth', 'Alliance Auth Documentation', (root_doc, 'allianceauth', 'Alliance Auth Documentation',
[author], 1) [author], 1)
] ]
@ -169,15 +137,12 @@ add_module_names = False
# Grouping the document tree into Texinfo files. List of tuples # Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [(
(master_doc, 'AllianceAuth', 'Alliance Auth Documentation', root_doc, 'AllianceAuth', 'Alliance Auth Documentation', author, 'AllianceAuth',
author, 'AllianceAuth', 'An auth system for EVE Online to help in-game organizations manage online service access.', 'An auth system for EVE Online to help in-game organizations manage online service access.', 'Miscellaneous'),
'Miscellaneous'),
] ]
def setup(app): # -- https://myst-parser.readthedocs.io/en/latest/configuration.html
app.add_config_value('recommonmark_config', {
'auto_toc_tree_section': 'Contents', myst_heading_anchors = 4
}, True)
app.add_transform(AutoStructify)

View File

@ -2,10 +2,9 @@
It is possible to customize your **Alliance Auth** instance. It is possible to customize your **Alliance Auth** instance.
```eval_rst :::{warning}
.. warning::
Keep in mind that you may need to update some of your customizations manually after new Auth releases (e.g. when replacing templates). Keep in mind that you may need to update some of your customizations manually after new Auth releases (e.g. when replacing templates).
``` :::
## Site name ## Site name
@ -82,7 +81,7 @@ First you need to create the folder for the template on your server. For AA to p
If you have a default installation you can create the folder like this: If you have a default installation you can create the folder like this:
```sh ```shell
mkdir -p /home/allianceserver/myauth/myauth/templates/allianceauth mkdir -p /home/allianceserver/myauth/myauth/templates/allianceauth
``` ```
@ -90,7 +89,7 @@ mkdir -p /home/allianceserver/myauth/myauth/templates/allianceauth
Next you need to download a copy of the original template file we want to change. For that let's move into the above folder and then download the file into the current folder with: Next you need to download a copy of the original template file we want to change. For that let's move into the above folder and then download the file into the current folder with:
```sh ```shell
cd /home/allianceserver/myauth/myauth/templates/allianceauth cd /home/allianceserver/myauth/myauth/templates/allianceauth
wget <https://gitlab.com/allianceauth/allianceauth/-/raw/master/allianceauth/templates/allianceauth/side-menu.html> wget <https://gitlab.com/allianceauth/allianceauth/-/raw/master/allianceauth/templates/allianceauth/side-menu.html>
``` ```
@ -99,11 +98,11 @@ wget <https://gitlab.com/allianceauth/allianceauth/-/raw/master/allianceauth/tem
Now you can modify the template to add your custom link. To create the google link we can add this snippet *between* the `{% menu_items %}` and the `</ul>` tag: Now you can modify the template to add your custom link. To create the google link we can add this snippet *between* the `{% menu_items %}` and the `</ul>` tag:
```sh ```shell
nano /home/allianceserver/myauth/myauth/templates/allianceauth/side-menu.html nano /home/allianceserver/myauth/myauth/templates/allianceauth/side-menu.html
``` ```
```jinja ```django
<li> <li>
<a href="https://www.google.com/" target="_blank"> <a href="https://www.google.com/" target="_blank">
<i class="fab fa-google fa-fw"></i>Google <i class="fab fa-google fa-fw"></i>Google
@ -111,10 +110,9 @@ nano /home/allianceserver/myauth/myauth/templates/allianceauth/side-menu.html
</li> </li>
``` ```
```eval_rst :::{hint}
.. hint::
You can find other icons with a matching style on the `Font Awesome site <https://fontawesome.com/v5/search?m=free>`_ . AA currently uses Font Awesome version 5. You also want to keep the ``fa-fw`` tag to ensure all icons have the same width. You can find other icons with a matching style on the `Font Awesome site <https://fontawesome.com/v5/search?m=free>`_ . AA currently uses Font Awesome version 5. You also want to keep the ``fa-fw`` tag to ensure all icons have the same width.
``` :::
### Step 4 - Restart your AA services ### Step 4 - Restart your AA services

View File

@ -10,7 +10,7 @@ To get started, `pip install pre-commit`, then `pre-commit install` to add the g
Before any code is "git push"-ed, pre-commit will check it for uniformity and correct it if possible Before any code is "git push"-ed, pre-commit will check it for uniformity and correct it if possible
```bash ```shell
check python ast.....................................(no files to check)Skipped check python ast.....................................(no files to check)Skipped
check yaml...........................................(no files to check)Skipped check yaml...........................................(no files to check)Skipped
check json...........................................(no files to check)Skipped check json...........................................(no files to check)Skipped

View File

@ -26,12 +26,14 @@ rearrange toctrees.
## Documentation Format ## Documentation Format
CommonMark Markdown is the current preferred format, via [recommonmark](https://github.com/rtfd/recommonmark). CommonMark-plus Markdown is the current preferred format, via [MyST-Parser](https://github.com/executablebooks/MyST-Parser).
reStructuredText is supported if required, or you can execute snippets of reST inside Markdown by using a code block: reStructuredText is supported if required, or you can execute snippets of MyST inside Markdown by using a code block:
```eval_rst ````md
```{eval-rst}
reStructuredText here reStructuredText here
``` ```
````
Markdown is used elsewhere on Github so it provides the most portability of documentation from Issues and Pull Requests Markdown is used elsewhere on Github so it provides the most portability of documentation from Issues and Pull Requests
as well as providing an easier initial migration path from the Github wiki. as well as providing an easier initial migration path from the Github wiki.

View File

@ -2,10 +2,9 @@
This section contains important information on how to develop Alliance Auth itself. This section contains important information on how to develop Alliance Auth itself.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
documentation documentation
code-style code-style
``` :::

View File

@ -2,14 +2,12 @@
This section describes how to extend **Alliance Auth** with custom apps, services and themes. This section describes how to extend **Alliance Auth** with custom apps, services and themes.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
integrating-services integrating-services
custom-themes
menu-hooks menu-hooks
url-hooks url-hooks
logging logging
css-framework css-framework
``` :::

View File

@ -50,10 +50,9 @@ def register_service():
This would register the ExampleService class which would need to be a subclass of `services.hooks.ServiceHook`. This would register the ExampleService class which would need to be a subclass of `services.hooks.ServiceHook`.
```eval_rst :::{important}
.. important::
The hook **MUST** be registered in ``yourservice.auth_hooks`` along with any other hooks you are registering for Alliance Auth. The hook **MUST** be registered in ``yourservice.auth_hooks`` along with any other hooks you are registering for Alliance Auth.
``` :::
A subclassed `ServiceHook` might look like this: A subclassed `ServiceHook` might look like this:
@ -79,7 +78,7 @@ Instance Variables:
- [self.name](#selfname) - [self.name](#selfname)
- [self.urlpatterns](#selfurlpatterns) - [self.urlpatterns](#selfurlpatterns)
- [self.service_ctrl_template](#selfservice-ctrl-template) - [self.service_ctrl_template](#selfservice_ctrl_template)
Properties: Properties:
@ -123,7 +122,9 @@ class MyService(ServiceHook):
All of your apps defined urlpatterns will then be included in the `URLconf` when the core application starts. All of your apps defined urlpatterns will then be included in the `URLconf` when the core application starts.
### Properties #### self.service_ctrl_template
This is provided as a courtesy and defines the default template to be used with [render_service_ctrl](#render_service_ctrl). You are free to redefine or not use this variable at all.
#### title #### title
@ -150,12 +151,14 @@ The function should return a boolean, `True` if successfully disabled, `False` o
Validate the users service account, deleting it if they should no longer have access. The `user` parameter should be a Django User object. Validate the users service account, deleting it if they should no longer have access. The `user` parameter should be a Django User object.
An implementation will probably look like the following: An implementation will probably look like the following:
```python ```python
def validate_user(self, user): def validate_user(self, user):
logger.debug('Validating user %s %s account' % (user, self.name)) logger.debug('Validating user %s %s account' % (user, self.name))
if ExampleTasks.has_account(user) and not self.service_active_for_user(user): if ExampleTasks.has_account(user) and not self.service_active_for_user(user):
self.delete_user(user, notify_user=True) self.delete_user(user, notify_user=True)
``` ```
No return value is expected. No return value is expected.
This function will be called periodically on all users to validate that the given user should have their current service accounts. This function will be called periodically on all users to validate that the given user should have their current service accounts.
@ -312,3 +315,9 @@ You should have a look through some of the other service modules before you get
## Testing ## Testing
You will need to add unit tests for all aspects of your service module before it is accepted. Be mindful that you don't actually want to make external calls to the service so you should mock the appropriate components to prevent this behavior. You will need to add unit tests for all aspects of your service module before it is accepted. Be mindful that you don't actually want to make external calls to the service so you should mock the appropriate components to prevent this behavior.
```{eval-rst}
.. autoclass:: allianceauth.services.hooks.ServicesHook
:members:
:undoc-members:
```

View File

@ -36,3 +36,11 @@ Options are: *(all options accept entries of levels listed below them)*
* `WARNING` * `WARNING`
* `ERROR` * `ERROR`
* `CRITICAL` * `CRITICAL`
## allianceauth.services.hooks.get_extension_logger
```{eval-rst}
.. automodule:: allianceauth.services.hooks.get_extension_logger
:members:
:undoc-members:
```

View File

@ -12,7 +12,7 @@ def register_menu():
The `MenuItemHook` class specifies some parameters/instance variables required for menu item display. The `MenuItemHook` class specifies some parameters/instance variables required for menu item display.
```eval_rst ```{eval-rst}
.. autoclass:: allianceauth.services.hooks.MenuItemHook .. autoclass:: allianceauth.services.hooks.MenuItemHook
:members: __init__ :members: __init__
:undoc-members: :undoc-members:
@ -24,23 +24,22 @@ The `MenuItemHook` class specifies some parameters/instance variables required f
This is a great feature to signal the user, that he has some open issues to take care of within an app. For example Auth uses this feature to show the specific number of open group request to the current user. This is a great feature to signal the user, that he has some open issues to take care of within an app. For example Auth uses this feature to show the specific number of open group request to the current user.
```eval_rst :::{hint}
.. hint::
Here is how to stay consistent with the Auth design philosophy for using this feature: Here is how to stay consistent with the Auth design philosophy for using this feature:
1. Use it to display open items that the current user can close by himself only. Do not use it for items, that the user has no control over. 1. Use it to display open items that the current user can close by himself only. Do not use it for items, that the user has no control over.
2. If there are currently no open items, do not show a badge at all. 2. If there are currently no open items, do not show a badge at all.
``` :::
To use it set count the `render()` function of your subclass in accordance to the current user. Here is an example: To use it set count the `render()` function of your subclass in accordance to the current user. Here is an example:
```eval_rst ```{eval-rst}
.. automodule:: allianceauth.services.hooks.MenuItemHook .. automodule:: allianceauth.services.hooks.MenuItemHook
:members: render :members: render
:noindex: :noindex:
:undoc-members: :undoc-members:
``` ```
```Python ```python
def render(self, request): def render(self, request):
# ... # ...
self.count = calculate_count_for_user(request.user) self.count = calculate_count_for_user(request.user)

View File

@ -30,10 +30,11 @@ In addition is it possible to make views public. Normally, all views are automat
An app can opt-out of this feature by adding a list of views to be excluded when registering the URLs. See the `excluded_views` parameter for details. An app can opt-out of this feature by adding a list of views to be excluded when registering the URLs. See the `excluded_views` parameter for details.
```eval_rst :::{note}
.. note::
Note that for a public view to work, administrators need to also explicitly allow apps to have public views in their AA installation, by adding the apps label to ``APPS_WITH_PUBLIC_VIEWS`` setting. Note that for a public view to work, administrators need to also explicitly allow apps to have public views in their AA installation, by adding the apps label to ``APPS_WITH_PUBLIC_VIEWS`` setting.
``` :::
>>>>>>>
## Examples ## Examples
An app called `plugin` provides a single view: An app called `plugin` provides a single view:
@ -70,7 +71,7 @@ When this app is included in the project's `settings.INSTALLED_APPS` users would
## API ## API
```eval_rst ```{eval-rst}
.. autoclass:: allianceauth.services.hooks.UrlHook .. autoclass:: allianceauth.services.hooks.UrlHook
:members: :members:
``` ```

View File

@ -6,10 +6,9 @@ The main benefit of this setup is that it runs all services and code in the nati
In addition all tools described in this guide are open source or free software. In addition all tools described in this guide are open source or free software.
```eval_rst :::{hint}
.. hint::
This guide is meant for development purposes only and not for installing AA in a production environment. For production installation please see chapter **Installation**. This guide is meant for development purposes only and not for installing AA in a production environment. For production installation please see chapter **Installation**.
``` :::
## Overview ## Overview
@ -25,10 +24,9 @@ The development environment consists of the following components:
We will use the build-in Django development web server, so we don't need to setup a WSGI server or a web server. We will use the build-in Django development web server, so we don't need to setup a WSGI server or a web server.
```eval_rst :::{note}
.. note::
This setup works with both WSL 1 and WSL 2. However, due to the significantly better performance we recommend WSL 2. This setup works with both WSL 1 and WSL 2. However, due to the significantly better performance we recommend WSL 2.
``` :::
## Requirement ## Requirement
@ -39,32 +37,27 @@ The only requirement is a PC with Windows 10 and Internet connection in order to
### Windows Subsystem for Linux ### Windows Subsystem for Linux
- Install from here: [Microsoft docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10) - Install from here: [Microsoft docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
- Choose Ubuntu 18.04. LTS or higher - Choose Ubuntu 18.04. LTS or higher
### Visual Studio Code ### Visual Studio Code
- Install from here: [VSC Download](https://code.visualstudio.com/Download) - Install from here: [VSC Download](https://code.visualstudio.com/Download)
- Open the app and install the following VSC extensions: - Open the app and install the following VSC extensions:
- Remote WSL - Remote WSL
- Connect to WSL. This will automatically install the VSC server on the VSC server for WSL - Connect to WSL. This will automatically install the VSC server on the VSC server for WSL
- Once connected to WSL install the Python extension on the WSL side - Once connected to WSL install the Python extension on the WSL side
## Setting up WSL / Linux ## Setting up WSL / Linux
Open a WSL bash and update all software packets: Open a WSL bash and update all software packets:
```bash ```shell
sudo apt update && sudo apt upgrade -y sudo apt update && sudo apt upgrade -y
``` ```
### Install Tools ### Install Tools
```bash ```shell
sudo apt-get install build-essential sudo apt-get install build-essential
sudo apt-get install gettext sudo apt-get install gettext
``` ```
@ -73,36 +66,33 @@ sudo apt-get install gettext
Next we need to install Python and related development tools. Next we need to install Python and related development tools.
```eval_rst :::{note}
.. hint::
To check your system's Python 3 version you can enter: ``python3 --version``
```
```eval_rst
.. note::
Should your Ubuntu come with a newer version of Python we recommend to still setup your dev environment with the oldest Python 3 version currently supported by AA (e.g Python 3.8 at this time of writing) to ensure your apps are compatible with all current AA installations Should your Ubuntu come with a newer version of Python we recommend to still setup your dev environment with the oldest Python 3 version currently supported by AA (e.g Python 3.8 at this time of writing) to ensure your apps are compatible with all current AA installations
You an check out this `page <https://askubuntu.com/questions/682869/how-do-i-install-a-different-python-version-using-apt-get/1195153>`_ on how to install additional Python versions on Ubuntu. You an check out this `page <https://askubuntu.com/questions/682869/how-do-i-install-a-different-python-version-using-apt-get/1195153>`_ on how to install additional Python versions on Ubuntu.
If you install a different python version from the default you need to adjust some of the commands below to install appopriate versions of those packages for example using Python 3.8 you might need to run the following after using the setup steps for the repository mentioned in the AskUbuntu post above: If you install a different python version from the default you need to adjust some of the commands below to install appopriate versions of those packages for example using Python 3.8 you might need to run the following after using the setup steps for the repository mentioned in the AskUbuntu post above:
`sudo apt-get install python3.8 python3.8-dev python3.8-venv python3-setuptools python3-pip python-pip` ```shell
sudo apt-get install python3.8 python3.8-dev python3.8-venv python3-setuptools python3-pip python-pip
``` ```
:::
Use the following command to install Python 3 with all required libraries with the default version: Use the following command to install Python 3 with all required libraries with the default version:
```bash ```shell
sudo apt-get install python3 python3-dev python3-venv python3-setuptools python3-pip python-pip sudo apt-get install python3 python3-dev python3-venv python3-setuptools python3-pip python-pip
``` ```
### Install redis and other tools ### Install redis and other tools
```bash ```shell
sudo apt-get install unzip git redis-server curl libssl-dev libbz2-dev libffi-dev pkg-config sudo apt-get install unzip git redis-server curl libssl-dev libbz2-dev libffi-dev pkg-config
``` ```
Start redis Start redis
```bash ```shell
sudo redis-server --daemonize yes sudo redis-server --daemonize yes
``` ```
@ -110,30 +100,29 @@ sudo redis-server --daemonize yes
Install MySQL and required libraries with the following command: Install MySQL and required libraries with the following command:
```bash ```shell
sudo apt-get install mysql-server mysql-client libmysqlclient-dev sudo apt-get install mysql-server mysql-client libmysqlclient-dev
``` ```
```eval_rst :::{note}
.. note::
We chose to use MySQL instead of MariaDB, because the standard version of MariaDB that comes with this Ubuntu distribution will not work with AA. We chose to use MySQL instead of MariaDB, because the standard version of MariaDB that comes with this Ubuntu distribution will not work with AA.
``` :::
We need to apply a permission fix to mysql or you will get a warning with every startup: We need to apply a permission fix to mysql or you will get a warning with every startup:
```bash ```shell
sudo usermod -d /var/lib/mysql/ mysql sudo usermod -d /var/lib/mysql/ mysql
``` ```
Start the mysql server Start the mysql server
```bash ```shell
sudo service mysql start sudo service mysql start
``` ```
Create database and user for AA Create database and user for AA
```bash ```shell
sudo mysql -u root sudo mysql -u root
``` ```
@ -147,23 +136,22 @@ exit;
Add timezone info to mysql: Add timezone info to mysql:
```bash ```shell
sudo mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -u root mysql sudo mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -u root mysql
``` ```
```eval_rst :::{note}
.. note::
If your WSL does not have an init.d service, it will not automatically start your services such as MySQL and Redis when you boot your Windows machine and you have to manually start them. For convenience we recommend putting these commands in a bash script. Here is an example: If your WSL does not have an init.d service, it will not automatically start your services such as MySQL and Redis when you boot your Windows machine and you have to manually start them. For convenience we recommend putting these commands in a bash script. Here is an example:
:: ```shell
#/bin/bash #/bin/bash
# start services for AA dev # start services for AA dev
sudo service mysql start sudo service mysql start
sudo redis-server --daemonize yes sudo redis-server --daemonize yes
``` ```
:::
### Setup dev folder on WSL ### Setup dev folder on WSL
Setup your folders on WSL bash for your dev project. Our approach will setup one AA project with one venv and multiple apps running under the same AA project, but each in their own folder and git. Setup your folders on WSL bash for your dev project. Our approach will setup one AA project with one venv and multiple apps running under the same AA project, but each in their own folder and git.
@ -183,28 +171,27 @@ Following this approach you can also setup additional AA projects, e.g. aa-dev-2
Create the root folder `aa-dev`. Create the root folder `aa-dev`.
```eval_rst :::{hint}
.. hint::
The folders `venv` and `myauth` will be created automatically in later steps. Please do not create them manually as this would lead to errors. The folders `venv` and `myauth` will be created automatically in later steps. Please do not create them manually as this would lead to errors.
``` :::
### Setup virtual Python environment for aa-dev ### Setup virtual Python environment for aa-dev
Create the virtual environment. Run this in your aa-dev folder: Create the virtual environment. Run this in your aa-dev folder:
```bash ```shell
python3 -m venv venv python3 -m venv venv
``` ```
And activate your venv: And activate your venv:
```bash ```shell
source venv/bin/activate source venv/bin/activate
``` ```
### Install and update basic Python packages ### Install and update basic Python packages
```bash ```shell
pip install -U pip setuptools wheel pip install -U pip setuptools wheel
``` ```
@ -212,19 +199,19 @@ pip install -U pip setuptools wheel
### Install and create AA instance ### Install and create AA instance
```bash ```shell
pip install allianceauth pip install allianceauth
``` ```
Now we are ready to setup our AA instance. Make sure to run this command in your aa-dev folder: Now we are ready to setup our AA instance. Make sure to run this command in your aa-dev folder:
```bash ```shell
allianceauth start myauth allianceauth start myauth
``` ```
Next we will setup our VSC project for aa-dev by starting it directly from the WSL bash: Next we will setup our VSC project for aa-dev by starting it directly from the WSL bash:
```bash ```shell
code . code .
``` ```
@ -244,10 +231,9 @@ For the Eve Online related setup you need to create a SSO app on the developer s
Open your local Django settings with VSC. The file is under `myauth/myauth/settings/local.py` Open your local Django settings with VSC. The file is under `myauth/myauth/settings/local.py`
```eval_rst :::{hint}
.. hint::
There are two Django settings files: ``base.py`` and ``local.py``. The base settings file is controlled by the AA project and may change at any time. It is therefore recommended to only change the local settings file. There are two Django settings files: ``base.py`` and ``local.py``. The base settings file is controlled by the AA project and may change at any time. It is therefore recommended to only change the local settings file.
``` :::
```python ```python
DEBUG = True DEBUG = True
@ -293,14 +279,14 @@ REGISTRATION_VERIFY_EMAIL = False
Before we can start AA we need to run migrations: Before we can start AA we need to run migrations:
```bash ```shell
cd myauth cd myauth
python manage.py migrate python manage.py migrate
``` ```
We also need to create a superuser for our AA installation: We also need to create a superuser for our AA installation:
```bash ```shell
python manage.py createsuperuser python manage.py createsuperuser
``` ```
@ -310,24 +296,22 @@ python manage.py createsuperuser
We are now ready to run out AA instance with the following command: We are now ready to run out AA instance with the following command:
```bash ```shell
python manage.py runserver python manage.py runserver
``` ```
Once running you can access your auth site on the browser under `http://localhost:8000`. Or the admin site under `http://localhost:8000/admin` Once running you can access your auth site on the browser under `http://localhost:8000`. Or the admin site under `http://localhost:8000/admin`
```eval_rst :::{hint}
.. hint::
You can start your AA server directly from a terminal window in VSC or with a VSC debug config (see chapter about debugging for details). You can start your AA server directly from a terminal window in VSC or with a VSC debug config (see chapter about debugging for details).
``` :::
```eval_rst :::{note}
.. note::
**Debug vs. Non-Debug mode** **Debug vs. Non-Debug mode**
Usually it is best to run your dev AA instance in debug mode, so you get all the detailed error messages that helps a lot for finding errors. But there might be cases where you want to test features that do not exist in debug mode (e.g. error pages) or just want to see how your app behaves in non-debug / production mode. Usually it is best to run your dev AA instance in debug mode, so you get all the detailed error messages that helps a lot for finding errors. But there might be cases where you want to test features that do not exist in debug mode (e.g. error pages) or just want to see how your app behaves in non-debug / production mode.
When you turn off debug mode you will see a problem though: Your pages will not render correctly. The reason is that Django will stop serving your static files in production mode and expect you to serve them from a real web server. Luckily, there is an option that forces Django to continue serving your static files directly even when not in debug mode. Just start your server with the following option: ``python manage.py runserver --insecure`` When you turn off debug mode you will see a problem though: Your pages will not render correctly. The reason is that Django will stop serving your static files in production mode and expect you to serve them from a real web server. Luckily, there is an option that forces Django to continue serving your static files directly even when not in debug mode. Just start your server with the following option: ``python manage.py runserver --insecure``
``` :::
### Celery ### Celery
@ -335,7 +319,7 @@ In addition you can start a celery worker instance for myauth. For development p
This can be done from the command line with the following command in the myauth folder (where manage.py is located): This can be done from the command line with the following command in the myauth folder (where manage.py is located):
```bash ```shell
celery -A myauth worker -l info -P solo celery -A myauth worker -l info -P solo
``` ```
@ -499,7 +483,7 @@ Open a WSL bash and navigate to the aa-dev folder. Make sure you have activate y
Run these commands: Run these commands:
```bash ```shell
git clone https://gitlab.com/ErikKalkoken/allianceauth-example-plugin.git git clone https://gitlab.com/ErikKalkoken/allianceauth-example-plugin.git
pip install -e allianceauth-example-plugin pip install -e allianceauth-example-plugin
``` ```
@ -508,7 +492,7 @@ Add `'example'` to INSTALLED_APPS in your `local.py` settings.
Run migrations and restart your AA server, e.g.: Run migrations and restart your AA server, e.g.:
```bash ```shell
cd myauth cd myauth
python manage.py migrate python manage.py migrate
``` ```

View File

@ -2,9 +2,8 @@
Here you find guides on how to setup your development environment for AA. Here you find guides on how to setup your development environment for AA.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
aa-dev-setup-wsl-vsc-v2 aa-dev-setup-wsl-vsc-v2
``` :::

View File

@ -2,12 +2,11 @@
**Alliance Auth** is designed to be extended easily. Learn how to develop your own apps and services for AA or to develop for AA core in the development chapter. **Alliance Auth** is designed to be extended easily. Learn how to develop your own apps and services for AA or to develop for AA core in the development chapter.
```eval_rst :::{toctree}
.. toctree:: :maxdepth: 1
:maxdepth: 2
custom/index custom/index
aa_core/index aa_core/index
dev_setup/index dev_setup/index
tech_docu/index tech_docu/index
``` :::

View File

@ -2,8 +2,7 @@
To reduce redundancy and help speed up development we encourage developers to utilize the following packages when developing apps for Alliance Auth. To reduce redundancy and help speed up development we encourage developers to utilize the following packages when developing apps for Alliance Auth.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
discord_client discord_client
@ -14,4 +13,4 @@ To reduce redundancy and help speed up development we encourage developers to ut
notifications notifications
testutils testutils
utils utils
``` :::

View File

@ -14,10 +14,9 @@ Alliance Auth is an online web application and as such the user expects fast and
As a rule of thumb we therefore recommend to use celery tasks for every process that can take longer than 1 sec to complete (also think about how long your process might take with large amounts of data). As a rule of thumb we therefore recommend to use celery tasks for every process that can take longer than 1 sec to complete (also think about how long your process might take with large amounts of data).
```eval_rst :::{note}
.. note::
Another solution for dealing with long response time in particular when loading pages is to load parts of a page asynchronously, for example with AJAX. Another solution for dealing with long response time in particular when loading pages is to load parts of a page asynchronously, for example with AJAX.
``` :::
### Recurrence ### Recurrence
@ -40,7 +39,7 @@ Please use the following approach to ensure your tasks are working properly with
Here is an example implementation of a task: Here is an example implementation of a task:
```Python ```python
import logging import logging
from celery import shared_task from celery import shared_task
@ -54,7 +53,7 @@ def example():
This task can then be started from any another Python module like so: This task can then be started from any another Python module like so:
```Python ```python
from .tasks import example from .tasks import example
example.delay() example.delay()
@ -80,7 +79,7 @@ However, many long running tasks consist of several smaller processes that need
Example implementation for a celery chain: Example implementation for a celery chain:
```Python ```python
import logging import logging
from celery import shared_task, chain from celery import shared_task, chain
@ -106,14 +105,13 @@ In this example we fist add 10 example tasks that need to run one after the othe
The list of task signatures is then converted to a chain and started asynchronously. The list of task signatures is then converted to a chain and started asynchronously.
```eval_rst :::{hint}
.. hint::
In our example we use ``si()``, which is a shortcut for "immutable signatures" and prevents us from having to deal with result sharing between tasks. In our example we use ``si()``, which is a shortcut for "immutable signatures" and prevents us from having to deal with result sharing between tasks.
For more information on signature and work flows see the official documentation on `Canvas <https://docs.celeryproject.org/en/latest/userguide/canvas.html>`_. For more information on signature and work flows see the official documentation on `Canvas <https://docs.celeryproject.org/en/latest/userguide/canvas.html>`_.
In this context please note that Alliance Auth currently only supports chaining, because all other variants require a so called results back, which Alliance Auth does not have. In this context please note that Alliance Auth currently only supports chaining, because all other variants require a so called results back, which Alliance Auth does not have.
``` :::
## How can I define periodic tasks for my app? ## How can I define periodic tasks for my app?
@ -121,7 +119,7 @@ Periodic tasks are normal celery tasks which are added the scheduler for periodi
Example setting: Example setting:
```Python ```python
CELERYBEAT_SCHEDULE['structures_update_all_structures'] = { CELERYBEAT_SCHEDULE['structures_update_all_structures'] = {
'task': 'structures.tasks.update_all_structures', 'task': 'structures.tasks.update_all_structures',
'schedule': crontab(minute='*/30'), 'schedule': crontab(minute='*/30'),
@ -137,7 +135,7 @@ CELERYBEAT_SCHEDULE['structures_update_all_structures'] = {
In Alliance Auth we have defined task priorities from 0 - 9 as follows: In Alliance Auth we have defined task priorities from 0 - 9 as follows:
```eval_rst ```{eval-rst}
====== ========= =========== ====== ========= ===========
Number Priority Description Number Priority Description
====== ========= =========== ====== ========= ===========
@ -150,30 +148,25 @@ In Alliance Auth we have defined task priorities from 0 - 9 as follows:
====== ========= =========== ====== ========= ===========
``` ```
```eval_rst :::{warning}
.. warning::
Please make sure to use task priorities with care and especially do not use higher priorities without a good reason. All apps including Alliance Auth share the same task queues, so using higher task priorities excessively can potentially prevent more important tasks (of other apps) from completing on time. Please make sure to use task priorities with care and especially do not use higher priorities without a good reason. All apps including Alliance Auth share the same task queues, so using higher task priorities excessively can potentially prevent more important tasks (of other apps) from completing on time.
You also want to make sure to run use lower priorities if you have a large amount of tasks or long running tasks, which are not super urgent. (e.g. the regular update of all Eve characters from ESI runs with priority 7) You also want to make sure to run use lower priorities if you have a large amount of tasks or long running tasks, which are not super urgent. (e.g. the regular update of all Eve characters from ESI runs with priority 7)
``` :::
:::{hint}
```eval_rst
.. hint::
If no priority is specified all tasks will be started with the default priority, which is 5. If no priority is specified all tasks will be started with the default priority, which is 5.
``` :::
To run a task with a different priority you need to specify it when starting it. To run a task with a different priority you need to specify it when starting it.
Example for starting a task with priority 3: Example for starting a task with priority 3:
```Python ```python
example.apply_async(priority=3) example.apply_async(priority=3)
``` ```
```eval_rst :::{hint}
.. hint::
For defining a priority to tasks you can not use the convenient shortcut ``delay()``, but instead need to start a task with ``apply_async()``, which also requires you to pass parameters to your task function differently. Please check out the `official docs <https://docs.celeryproject.org/en/stable/reference/celery.app.task.html#celery.app.task.Task.apply_async>`_ for details. For defining a priority to tasks you can not use the convenient shortcut ``delay()``, but instead need to start a task with ``apply_async()``, which also requires you to pass parameters to your task function differently. Please check out the `official docs <https://docs.celeryproject.org/en/stable/reference/celery.app.task.html#celery.app.task.Task.apply_async>`_ for details.
``` :::
## What special features should I be aware of? ## What special features should I be aware of?
@ -186,18 +179,18 @@ Celery-once is a celery extension "that allows you to prevent multiple execution
We use a custom backend for celery_once in Alliance Auth defined [here](https://gitlab.com/allianceauth/allianceauth/-/blob/master/allianceauth/services/tasks.py#L14) We use a custom backend for celery_once in Alliance Auth defined [here](https://gitlab.com/allianceauth/allianceauth/-/blob/master/allianceauth/services/tasks.py#L14)
You can import it for use like so: You can import it for use like so:
```Python ```python
from allianceauth.services.tasks import QueueOnce from allianceauth.services.tasks import QueueOnce
``` ```
An example of AllianceAuth's use within the `@sharedtask` decorator, can be seen [here](https://gitlab.com/allianceauth/allianceauth/-/blob/master/allianceauth/services/modules/discord/tasks.py#L62) in the discord module An example of AllianceAuth's use within the `@sharedtask` decorator, can be seen [here](https://gitlab.com/allianceauth/allianceauth/-/blob/master/allianceauth/services/modules/discord/tasks.py#L62) in the discord module
You can use it like so: You can use it like so:
```Python ```python
@shared_task(bind=True, name='your_modules.update_task', base=QueueOnce) @shared_task(bind=True, name='your_modules.update_task', base=QueueOnce)
``` ```
Please see the [official documentation](hhttps://pypi.org/project/celery_once/) of celery-once for details. Please see the [official documentation](https://pypi.org/project/celery_once/) of celery-once for details.
### task priorities ### task priorities

View File

@ -2,12 +2,11 @@
In this section you find topics useful for app developers. In this section you find topics useful for app developers.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
api/index api/index
celery celery
core_models core_models
templatetags templatetags
``` :::

View File

@ -1,10 +1,5 @@
# Auto Groups # Auto Groups
```eval_rst
.. note::
New in 2.0
```
Auto groups allows you to automatically place users of certain states into Corp or Alliance based groups. These groups are created when the first user is added to them and removed when the configuration is deleted. Auto groups allows you to automatically place users of certain states into Corp or Alliance based groups. These groups are created when the first user is added to them and removed when the configuration is deleted.
## Installation ## Installation
@ -19,26 +14,21 @@ When you create an autogroup config you will be given the following options:
![Create Autogroup page](/_static/images/features/apps/autogroups/group-creation.png) ![Create Autogroup page](/_static/images/features/apps/autogroups/group-creation.png)
```eval_rst :::{warning}
.. warning::
After creating a group you wont be able to change the Corp and Alliance group prefixes, name source and the replace spaces settings. Make sure you configure these the way you want before creating the config. If you need to change these you will have to create a new autogroup config. After creating a group you wont be able to change the Corp and Alliance group prefixes, name source and the replace spaces settings. Make sure you configure these the way you want before creating the config. If you need to change these you will have to create a new autogroup config.
``` :::
- States selects which states will be added to automatic Corp/Alliance groups - States selects which states will be added to automatic Corp/Alliance groups
- Corp/Alliance groups checkbox toggles Corp/Alliance autogroups on or off for this config. - Corp/Alliance groups checkbox toggles Corp/Alliance autogroups on or off for this config.
- Corp/Alliance group prefix sets the prefix for the group name, e.g. if your Corp was called `MyCorp` and your prefix was `Corp`, your autogroup name would be created as `Corp MyCorp`. This field accepts leading/trailing spaces. - Corp/Alliance group prefix sets the prefix for the group name, e.g. if your Corp was called `MyCorp` and your prefix was `Corp`, your autogroup name would be created as `Corp MyCorp`. This field accepts leading/trailing spaces.
- 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 ## Permissions
Auto Groups are configured via models in the Admin Interface, a user will require the `Staff` Flag in addition to the following 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 ```{eval-rst}
+-------------------------------------------+------------------+----------------+ +-------------------------------------------+------------------+----------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+===========================================+==================+================+ +===========================================+==================+================+

View File

@ -90,7 +90,7 @@ Characters from all Corp Stats to which the user has view access will be display
To use this feature, users will require some of the following: To use this feature, users will require some of the following:
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+----------------------------------------------------+ +---------------------------------------+------------------+----------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+====================================================+ +=======================================+==================+====================================================+

View File

@ -16,7 +16,7 @@ To administer this feature, users will require some of the following.
Users do not require any permissions to interact with FAT Links created. Users do not require any permissions to interact with FAT Links created.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+
@ -24,5 +24,4 @@ Users do not require any permissions to interact with FAT Links created.
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| auth.fleetactivitytracking_statistics | None | Can view detailed statistics for corp models and other characters. | | auth.fleetactivitytracking_statistics | None | Can view detailed statistics for corp models and other characters. |
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
``` ```

View File

@ -44,7 +44,7 @@ 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. Users do not require any permission to apply to a corporation and fill out the form.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+----------------------------------------------------+ +---------------------------------------+------------------+----------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+====================================================+ +=======================================+==================+====================================================+

View File

@ -2,8 +2,7 @@
**Alliance Auth** comes with a set of apps (also called plugin-apps) which provide basic functions useful to many organizations in Eve Online like a fleet schedule and a timerboard. This section describes which apps are available and how to install and use them. Please note that any app need to be installed before it can be used. **Alliance Auth** comes with a set of apps (also called plugin-apps) which provide basic functions useful to many organizations in Eve Online like a fleet schedule and a timerboard. This section describes which apps are available and how to install and use them. Please note that any app need to be installed before it can be used.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
autogroups autogroups
@ -14,4 +13,4 @@
permissions_tool permissions_tool
srp srp
timerboard timerboard
``` :::

View File

@ -12,7 +12,7 @@ Add `'allianceauth.optimer',` to your `INSTALLED_APPS` list in your auth project
To use and administer this feature, users will require some of the following. To use and administer this feature, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -42,7 +42,7 @@ Please note that users may appear multiple times if this permission is granted v
To use this feature, users will require some of the following. To use this feature, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -12,7 +12,7 @@ Add `'allianceauth.srp',` to your `INSTALLED_APPS` list in your auth project's s
To use and administer this feature, users will require some of the following. To use and administer this feature, users will require some of the following.
```eval_rst ```{eval-rst}
+----------------------+------------------+------------------------------------------------------------+ +----------------------+------------------+------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+======================+==================+============================================================+ +======================+==================+============================================================+

View File

@ -12,7 +12,7 @@ Add `'allianceauth.timerboard',` to your `INSTALLED_APPS` list in your auth proj
To use and administer this feature, users will require some of the following. To use and administer this feature, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -10,10 +10,9 @@ You can open the admin site by clicking on "Admin" in the drop down menu for a u
For small to medium size alliances it is often sufficient to have no more then two superuser admins (admins that also are superusers). Having two admins usually makes sense, so you can have one primary and one backup. For small to medium size alliances it is often sufficient to have no more then two superuser admins (admins that also are superusers). Having two admins usually makes sense, so you can have one primary and one backup.
```eval_rst :::{warning}
.. warning::
Superusers have read & write access to everything on your AA installation. Superusers also automatically have all permissions and therefore access to all features of your apps. Therefore we recommend to be very careful to whom you give superuser privileges. Superusers have read & write access to everything on your AA installation. Superusers also automatically have all permissions and therefore access to all features of your apps. Therefore we recommend to be very careful to whom you give superuser privileges.
``` :::
## Setup for large installations ## Setup for large installations
@ -26,8 +25,7 @@ To create a staff admin you need to do two things:
1. Enable the `is_staff` property for a user 1. Enable the `is_staff` property for a user
1. Give the user permissions for admin tasks 1. Give the user permissions for admin tasks
```eval_rst :::{note}
.. note::
Note that staff admins have the following limitations: Note that staff admins have the following limitations:
- Can not promote users to staff - Can not promote users to staff
@ -35,17 +33,17 @@ To create a staff admin you need to do two things:
- Can not add/remove permissions for users, groups and states - Can not add/remove permissions for users, groups and states
These limitations exist to prevent staff admins to promote themselves to quasi superusers. Only superusers can perform these actions. These limitations exist to prevent staff admins to promote themselves to quasi superusers. Only superusers can perform these actions.
```
:::
### Staff property ### Staff property
Access to the admin site is restricted. Users needs to have the `is_staff` property to be able to open the site at all. The superuser that is created during the installation Access to the admin site is restricted. Users needs to have the `is_staff` property to be able to open the site at all. The superuser that is created during the installation
process will automatically have access to the admin site. process will automatically have access to the admin site.
```eval_rst :::{hint}
.. hint::
Without any permissions a "staff user" can open the admin site, but can neither view nor edit anything except for viewing the list of permissions. Without any permissions a "staff user" can open the admin site, but can neither view nor edit anything except for viewing the list of permissions.
``` :::
### Permissions for common admin tasks ### Permissions for common admin tasks

View File

@ -64,7 +64,7 @@ This data is stored in a Team Google Analytics Dashboard. The Maintainers all ha
### Analytics Event ### Analytics Event
```eval_rst ```{eval-rst}
.. automodule:: allianceauth.analytics.tasks .. automodule:: allianceauth.analytics.tasks
:members: analytics_event :members: analytics_event
:undoc-members: :undoc-members:

View File

@ -13,7 +13,7 @@ For admin users the dashboard shows additional technical information about the
Here is a list of available settings for the dashboard. They can be configured by adding them to your AA settings file (``local.py``). Here is a list of available settings for the dashboard. They can be configured by adding them to your AA settings file (``local.py``).
Note that all settings are optional and the app will use the documented default settings if they are not used. Note that all settings are optional and the app will use the documented default settings if they are not used.
```eval_rst ```{eval-rst}
+-----------------------------------------------------+-------------------------------------------------------------------------+-----------+ +-----------------------------------------------------+-------------------------------------------------------------------------+-----------+
| Name | Description | Default | | Name | Description | Default |
+=====================================================+=========================================================================+===========+ +=====================================================+=========================================================================+===========+

View File

@ -42,7 +42,7 @@ Most people won't have a use for public groups, though it can be useful if you w
When a group is restricted only superuser admins can directly add or remove them to/from users. The purpose of this property is prevent staff admins from assigning themselves to groups that are security sensitive. The "restricted" property can be combined with all the other properties. When a group is restricted only superuser admins can directly add or remove them to/from users. The purpose of this property is prevent staff admins from assigning themselves to groups that are security sensitive. The "restricted" property can be combined with all the other properties.
```eval_rst ```{eval-rst}
.. _ref-reserved-group-names: .. _ref-reserved-group-names:
``` ```
@ -50,10 +50,9 @@ When a group is restricted only superuser admins can directly add or remove them
When using Alliance Auth to manage external services like Discord, Auth will automatically duplicate groups on those services. E.g. on Discord Auth will create roles of the same name as groups. However, there may be cases where you want to manage groups on external services by yourself or by another bot. For those cases you can define a list of reserved group names. Auth will ensure that you can not create groups with a reserved name. You will find this list on the admin site under groupmanagement. When using Alliance Auth to manage external services like Discord, Auth will automatically duplicate groups on those services. E.g. on Discord Auth will create roles of the same name as groups. However, there may be cases where you want to manage groups on external services by yourself or by another bot. For those cases you can define a list of reserved group names. Auth will ensure that you can not create groups with a reserved name. You will find this list on the admin site under groupmanagement.
```eval_rst :::{note}
.. note::
While this feature can help to avoid naming conflicts with groups on external services, the respective service component in Alliance Auth also needs to be build in such a way that it knows how to prevent these conflicts. Currently only the Discord and Teamspeak3 services have this ability. While this feature can help to avoid naming conflicts with groups on external services, the respective service component in Alliance Auth also needs to be build in such a way that it knows how to prevent these conflicts. Currently only the Discord and Teamspeak3 services have this ability.
``` :::
## Managing groups ## Managing groups
@ -101,17 +100,16 @@ By default, in AA both requests and leaves for non-open groups must be approved
GROUPMANAGEMENT_AUTO_LEAVE = True GROUPMANAGEMENT_AUTO_LEAVE = True
``` ```
```eval_rst :::{note}
.. note::
Before you set `GROUPMANAGEMENT_AUTO_LEAVE = True`, make sure there are no pending leave requests, as this option will hide the "Leave Requests" tab. Before you set `GROUPMANAGEMENT_AUTO_LEAVE = True`, make sure there are no pending leave requests, as this option will hide the "Leave Requests" tab.
``` :::
## Settings ## Settings
Here is a list of available settings for Group Management. They can be configured by adding them to your AA settings file (``local.py``). Here is a list of available settings for Group Management. They can be configured by adding them to your AA settings file (``local.py``).
Note that all settings are optional and the app will use the documented default settings if they are not used. Note that all settings are optional and the app will use the documented default settings if they are not used.
```eval_rst ```{eval-rst}
+---------------------------------------------+---------------------------------------------------------------------------+------------+ +---------------------------------------------+---------------------------------------------------------------------------+------------+
| Name | Description | Default | | Name | Description | Default |
+=============================================+===========================================================================+============+ +=============================================+===========================================================================+============+
@ -127,14 +125,13 @@ In order to join a group other than a public group, the permission `groupmanagem
When a user loses this permission, they will be removed from all groups _except_ Public groups. When a user loses this permission, they will be removed from all groups _except_ Public groups.
```eval_rst :::{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.
``` :::
Group Management should be mostly done using group leaders, a series of permissions are included below for thoroughness: Group Management should be mostly done using group leaders, a series of permissions are included below for thoroughness:
```eval_rst ```{eval-rst}
+--------------------------------+-------------------+------------------------------------------------------------------------------------+ +--------------------------------+-------------------+------------------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+================================+===================+====================================================================================+ +================================+===================+====================================================================================+

View File

@ -2,8 +2,7 @@
Managing access to applications and services is one of the core functions of **Alliance Auth**. The related key concepts and functionalities are describes in this section. Managing access to applications and services is one of the core functions of **Alliance Auth**. The related key concepts and functionalities are describes in this section.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
dashboard dashboard
@ -12,4 +11,4 @@ Managing access to applications and services is one of the core functions of **A
analytics analytics
notifications notifications
admin_site admin_site
``` :::

View File

@ -2,8 +2,7 @@
Learn about the features of **Alliance Auth** and how to install and use them. Learn about the features of **Alliance Auth** and how to install and use them.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
overview overview
@ -11,4 +10,4 @@ Learn about the features of **Alliance Auth** and how to install and use them.
services/index services/index
apps/index apps/index
community/index community/index
``` :::

View File

@ -33,10 +33,9 @@ CELERYBEAT_SCHEDULE['discord.update_all_usernames'] = {
} }
``` ```
```eval_rst :::{note}
.. note::
You will have to add most the values for these settings, e.g. your Discord server ID (aka guild ID), later in the setup process. You will have to add most the values for these settings, e.g. your Discord server ID (aka guild ID), later in the setup process.
``` :::
### Creating a Server ### Creating a Server
@ -48,11 +47,9 @@ Now retrieve the server ID [following this procedure.](https://support.discord.c
Update your auth project's settings file, inputting the server ID as `DISCORD_GUILD_ID` Update your auth project's settings file, inputting the server ID as `DISCORD_GUILD_ID`
```eval_rst :::{note}
.. note::
If you already have a Discord server skip the creation step, but be sure to retrieve the server ID If you already have a Discord server skip the creation step, but be sure to retrieve the server ID
``` :::
### Registering an Application ### Registering an Application
Navigate to the [Discord Developers site.](https://discord.com/developers/applications/me) Press the plus sign to create a new application. Navigate to the [Discord Developers site.](https://discord.com/developers/applications/me) Press the plus sign to create a new application.
@ -107,27 +104,25 @@ Second, it is possible to exclude Discord roles from being managed by Auth at al
To exclude roles from being managed by Auth you only have to add them to the list of reserved group names in Group Management. To exclude roles from being managed by Auth you only have to add them to the list of reserved group names in Group Management.
```eval_rst :::{note}
.. note::
Role names on Discord are case sensitive, while reserved group names on Auth are not. Therefore reserved group names will cover all roles regardless of their case. For example if you have reserved the group name "alpha", then the Discord roles "alpha" and "Alpha" will both be persisted. Role names on Discord are case sensitive, while reserved group names on Auth are not. Therefore reserved group names will cover all roles regardless of their case. For example if you have reserved the group name "alpha", then the Discord roles "alpha" and "Alpha" will both be persisted.
``` :::
```eval_rst ```{eval-rst}
.. seealso:: .. seealso::
For more information see :ref:`ref-reserved-group-names`. For more information see :ref:`ref-reserved-group-names`.
``` ```
## Tasks ## Tasks
The Discord service contains a number of tasks that can be run to manually perform updates to all users. The Discord service contains a number of tasks that can be run to manually perform updates to all users.
You can run any of these tasks from the command line. Please make sure that you are in your venv and then you can run this command from the same folder that your manage.py is located: You can run any of these tasks from the command line. Please make sure that you are in your venv and then you can run this command from the same folder that your manage.py is located:
```bash ```shell
celery -A myauth call discord.update_all_groups celery -A myauth call discord.update_all_groups
``` ```
```eval_rst ```{eval-rst}
======================== ==================================================== ======================== ====================================================
Name Description Name Description
======================== ==================================================== ======================== ====================================================
@ -137,17 +132,15 @@ Name Description
`update_all` Update groups, nicknames, usernames of all users `update_all` Update groups, nicknames, usernames of all users
======================== ==================================================== ======================== ====================================================
``` ```
:::{note}
```eval_rst
.. note::
Depending on how many users you have, running these tasks can take considerable time to finish. You can calculate roughly 1 sec per user for all tasks, except update_all, which needs roughly 3 secs per user. Depending on how many users you have, running these tasks can take considerable time to finish. You can calculate roughly 1 sec per user for all tasks, except update_all, which needs roughly 3 secs per user.
``` :::
## Settings ## Settings
You can configure your Discord services with the following settings: You can configure your Discord services with the following settings:
```eval_rst ```{eval-rst}
=================================== ============================================================================================= ======= =================================== ============================================================================================= =======
Name Description Default Name Description Default
=================================== ============================================================================================= ======= =================================== ============================================================================================= =======
@ -163,19 +156,17 @@ Name Description
`DISCORD_TASKS_MAX_RETRIES` max retries of tasks after an error occurred `3` `DISCORD_TASKS_MAX_RETRIES` max retries of tasks after an error occurred `3`
=================================== ============================================================================================= ======= =================================== ============================================================================================= =======
``` ```
## Permissions ## Permissions
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+
| discord.access_discord | None | Can Access the Discord Service | | 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

View File

@ -17,7 +17,7 @@ DISCOURSE_SSO_SECRET = ''
## Install Docker ## Install Docker
```bash ```shell
wget -qO- https://get.docker.io/ | sh wget -qO- https://get.docker.io/ | sh
``` ```
@ -25,14 +25,14 @@ wget -qO- https://get.docker.io/ | sh
### Download Discourse ### Download Discourse
```bash ```shell
mkdir /var/discourse mkdir /var/discourse
git clone https://github.com/discourse/discourse_docker.git /var/discourse git clone https://github.com/discourse/discourse_docker.git /var/discourse
``` ```
### Configure ### Configure
```bash ```shell
cd /var/discourse cd /var/discourse
cp samples/standalone.yml containers/app.yml cp samples/standalone.yml containers/app.yml
nano containers/app.yml nano containers/app.yml
@ -68,7 +68,7 @@ Or any other port will do, if taken. Remember this number.
### Build and launch ### Build and launch
```bash ```shell
nano /etc/default/docker nano /etc/default/docker
``` ```
@ -80,13 +80,13 @@ Uncomment this line:
Restart Docker: Restart Docker:
```bash ```shell
service docker restart service docker restart
``` ```
Now build: Now build:
```bash ```shell
./launcher bootstrap app ./launcher bootstrap app
./launcher start app ./launcher start app
``` ```
@ -124,7 +124,7 @@ server {
From the `/var/discourse` directory, From the `/var/discourse` directory,
```bash ```shell
./launcher enter app ./launcher enter app
rake admin:create rake admin:create
``` ```
@ -157,7 +157,7 @@ Finally run migrations and restart Gunicorn and Celery.
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -4,8 +4,7 @@
## Supported Services ## Supported Services
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
discord discord
@ -16,14 +15,13 @@
smf smf
teamspeak3 teamspeak3
xenforo xenforo
``` :::
## Tools ## Tools
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
nameformats nameformats
permissions permissions
``` :::

View File

@ -2,53 +2,57 @@
Mumble is a free voice chat server. While not as flashy as TeamSpeak, it has all the functionality and is easier to customize. And is better. I may be slightly biased. Mumble is a free voice chat server. While not as flashy as TeamSpeak, it has all the functionality and is easier to customize. And is better. I may be slightly biased.
```eval_rst :::{note}
.. note::
Note that this guide assumes that you have installed Auth with the official :doc:`/installation/allianceauth` guide under ``/home/allianceserver`` and that it is called ``myauth``. Accordingly it assumes that you have a service user called ``allianceserver`` that is used to run all Auth services under supervisor. Note that this guide assumes that you have installed Auth with the official :doc:`/installation/allianceauth` guide under ``/home/allianceserver`` and that it is called ``myauth``. Accordingly it assumes that you have a service user called ``allianceserver`` that is used to run all Auth services under supervisor.
``` :::
```eval_rst :::{warning}
.. warning::
This guide is currently for Ubuntu only. This guide is currently for Ubuntu only.
``` :::
## Installations ## Installations
### Installing Mumble Server ### Installing Mumble Server
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
The mumble server package can be retrieved from a repository, which we need to add: The mumble server package can be retrieved from a repository, which we need to add:
```bash ```shell
sudo apt-add-repository ppa:mumble/release sudo apt-add-repository ppa:mumble/release
``` ```
```bash ```shell
sudo apt-get update sudo apt-get update
``` ```
Now three packages need to be installed: Now three packages need to be installed:
```bash ```shell
sudo apt-get install python-software-properties mumble-server libqt5sql5-mysql sudo apt-get install python-software-properties mumble-server libqt5sql5-mysql
``` ```
:::
::::
### Installing Mumble Authenticator ### Installing Mumble Authenticator
Next, we need to download the latest authenticator release from the [authenticator repository](https://gitlab.com/allianceauth/mumble-authenticator). Next, we need to download the latest authenticator release from the [authenticator repository](https://gitlab.com/allianceauth/mumble-authenticator).
```bash ```shell
git clone https://gitlab.com/allianceauth/mumble-authenticator /home/allianceserver/mumble-authenticator git clone https://gitlab.com/allianceauth/mumble-authenticator /home/allianceserver/mumble-authenticator
``` ```
We will now install the authenticator into your Auth virtual environment. Please make sure to activate it first: We will now install the authenticator into your Auth virtual environment. Please make sure to activate it first:
```bash ```shell
source /home/allianceserver/venv/auth/bin/activate source /home/allianceserver/venv/auth/bin/activate
``` ```
Install the python dependencies for the mumble authenticator. Note that this process can take 2-10 minutes to complete. Install the python dependencies for the mumble authenticator. Note that this process can take 2-10 minutes to complete.
```bash ```shell
pip install -r requirements.txt pip install -r requirements.txt
``` ```
@ -66,7 +70,7 @@ GRANT ALL PRIVILEGES ON alliance_mumble . * TO 'allianceserver'@'localhost';
Mumble ships with a configuration file that needs customization. By default its located at `/etc/mumble-server.ini`. Open it with your favorite text editor: Mumble ships with a configuration file that needs customization. By default its located at `/etc/mumble-server.ini`. Open it with your favorite text editor:
```bash ```shell
sudo nano /etc/mumble-server.ini sudo nano /etc/mumble-server.ini
``` ```
@ -90,7 +94,7 @@ Save and close the file.
To get Mumble superuser account credentials, run the following: To get Mumble superuser account credentials, run the following:
```bash ```shell
sudo dpkg-reconfigure mumble-server sudo dpkg-reconfigure mumble-server
``` ```
@ -98,7 +102,7 @@ Set the password to something youll remember and write it down. This is your
Now restart the server to see the changes reflected. Now restart the server to see the changes reflected.
```bash ```shell
sudo service mumble-server restart sudo service mumble-server restart
``` ```
@ -110,7 +114,7 @@ The ICE authenticator lives in the mumble-authenticator repository, cd to the di
Make a copy of the default config: Make a copy of the default config:
```bash ```shell
cp authenticator.ini.example authenticator.ini cp authenticator.ini.example authenticator.ini
``` ```
@ -124,19 +128,19 @@ Edit `authenticator.ini` and change these values:
Test your configuration by starting it: Test your configuration by starting it:
```bash ```shell
python /home/allianceserver/mumble-authenticator/authenticator.py python /home/allianceserver/mumble-authenticator/authenticator.py
``` ```
And finally ensure the allianceserver user has read/write permissions to the mumble authenticator files before proceeding: And finally ensure the allianceserver user has read/write permissions to the mumble authenticator files before proceeding:
```bash ```shell
sudo chown -R allianceserver:allianceserver /home/allianceserver/mumble-authenticator sudo chown -R allianceserver:allianceserver /home/allianceserver/mumble-authenticator
``` ```
The authenticator needs to be running 24/7 to validate users on Mumble. This can be achieved by adding a section to your auth project's supervisor config file like the following example: The authenticator needs to be running 24/7 to validate users on Mumble. This can be achieved by adding a section to your auth project's supervisor config file like the following example:
```text ```ini
[program:authenticator] [program:authenticator]
command=/home/allianceserver/venv/auth/bin/python authenticator.py command=/home/allianceserver/venv/auth/bin/python authenticator.py
directory=/home/allianceserver/mumble-authenticator directory=/home/allianceserver/mumble-authenticator
@ -151,7 +155,7 @@ priority=996
In addition we'd recommend to add the authenticator to Auth's restart group in your supervisor conf. For that you need to add it to the group line as shown in the following example: In addition we'd recommend to add the authenticator to Auth's restart group in your supervisor conf. For that you need to add it to the group line as shown in the following example:
```text ```ini
[group:myauth] [group:myauth]
programs=beat,worker,gunicorn,authenticator programs=beat,worker,gunicorn,authenticator
priority=999 priority=999
@ -159,7 +163,7 @@ priority=999
To enable the changes in your supervisor configuration you need to restart the supervisor process itself. And before we do that we are shutting down the current Auth supervisors gracefully: To enable the changes in your supervisor configuration you need to restart the supervisor process itself. And before we do that we are shutting down the current Auth supervisors gracefully:
```bash ```shell
sudo supervisor stop myauth: sudo supervisor stop myauth:
sudo systemctl restart supervisor sudo systemctl restart supervisor
``` ```
@ -187,11 +191,11 @@ MUMBLE_URL = "mumble.example.com"
Finally, run migrations and restart your supervisor to complete the setup: Finally, run migrations and restart your supervisor to complete the setup:
```bash ```shell
python /home/allianceserver/myauth/manage.py migrate python /home/allianceserver/myauth/manage.py migrate
``` ```
```bash ```shell
supervisorctl restart myauth: supervisorctl restart myauth:
``` ```
@ -199,7 +203,7 @@ supervisorctl restart myauth:
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+
@ -262,19 +266,19 @@ If Push to Talk is to your tastes, configure the suggestion as follows
With the default configuration your mumble server is public. Meaning that everyone who has the address can at least connect to it and might also be able join all channels that don't have any permissions set (Depending on your ACL configured for the root channel). If you want only registered member being able to join your mumble, you have to set a server password. To do so open your mumble server configuration which is by default located at `/etc/mumble-server.ini`. With the default configuration your mumble server is public. Meaning that everyone who has the address can at least connect to it and might also be able join all channels that don't have any permissions set (Depending on your ACL configured for the root channel). If you want only registered member being able to join your mumble, you have to set a server password. To do so open your mumble server configuration which is by default located at `/etc/mumble-server.ini`.
```bash ```shell
sudo nano /etc/mumble-server.ini sudo nano /etc/mumble-server.ini
``` ```
Now search for `serverpassword=` and set your password here. If there is no such line, simply add it. Now search for `serverpassword=` and set your password here. If there is no such line, simply add it.
```text ```ini
serverpassword=YourSuperSecretServerPassword serverpassword=YourSuperSecretServerPassword
``` ```
Save the file and restart your mumble server afterwards. Save the file and restart your mumble server afterwards.
```bash ```shell
sudo service mumble-server restart sudo service mumble-server restart
``` ```

View File

@ -6,7 +6,7 @@ Each service's username or nickname, depending on which the service supports, ca
Currently the following services support custom name formats: Currently the following services support custom name formats:
```eval_rst ```{eval-rst}
+-------------+-----------+-------------------------------------+ +-------------+-----------+-------------------------------------+
| Service | Used with | Default Formatter | | Service | Used with | Default Formatter |
+=============+===========+=====================================+ +=============+===========+=====================================+
@ -29,11 +29,9 @@ Currently the following services support custom name formats:
| Xenforo | Username | ``{character_name}`` | | Xenforo | Username | ``{character_name}`` |
+-------------+-----------+-------------------------------------+ +-------------+-----------+-------------------------------------+
``` ```
:::{note}
```eval_rst
.. note::
It's important to note here, before we get into what you can do with a name formatter, that before the generated name is passed off to the service to create an account it will be sanitized to remove characters (the letters and numbers etc.) that the service cannot support. This means that, despite what you configured, the service may display something different. It is up to you to test your formatter and understand how your format may be disrupted by a certain services sanitization function. It's important to note here, before we get into what you can do with a name formatter, that before the generated name is passed off to the service to create an account it will be sanitized to remove characters (the letters and numbers etc.) that the service cannot support. This means that, despite what you configured, the service may display something different. It is up to you to test your formatter and understand how your format may be disrupted by a certain services sanitization function.
``` :::
## Available format data ## Available format data
@ -59,7 +57,7 @@ A more digestible documentation of string formatting in Python is available on t
Some examples of strings you could use: Some examples of strings you could use:
```eval_rst ```{eval-rst}
+------------------------------------------+---------------------------+ +------------------------------------------+---------------------------+
| Formatter | Result | | Formatter | Result |
+==========================================+===========================+ +==========================================+===========================+
@ -71,12 +69,10 @@ Some examples of strings you could use:
+------------------------------------------+---------------------------+ +------------------------------------------+---------------------------+
``` ```
```eval_rst :::{important}
.. important::
For most services, name formats only take effect when a user creates an account. This means if you create or update a name formatter it wont retroactively alter the format of users names. There are some exceptions to this where the service updates nicknames on a periodic basis. Check the service's documentation to see which of these apply. For most services, name formats only take effect when a user creates an account. This means if you create or update a name formatter it wont retroactively alter the format of users names. There are some exceptions to this where the service updates nicknames on a periodic basis. Check the service's documentation to see which of these apply.
``` :::
```eval_rst :::{important}
.. important:: You must only create one formatter per service per state. E.g. don't create two formatters for Mumble for the Member state. In this case one of the formatters will be used and it may not be the formatter you are expecting:
You must only create one formatter per service per state. E.g. don't create two formatters for Mumble for the Member state. In this case one of the formatters will be used and it may not be the formatter you are expecting. :::
```

View File

@ -23,23 +23,37 @@ BROADCAST_SERVICE_NAME = "broadcast"
Openfire require a Java 8 runtime environment. Openfire require a Java 8 runtime environment.
Ubuntu 1804, 2004, 2204: ::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
```bash ```shell
sudo apt-get install openjdk-11-jre sudo apt-get install openjdk-11-jre
``` ```
Centos 7: :::
:::{group-tab} CentOS 7
```bash ```shell
sudo yum install java-11-openjdk java-11-openjdk-devel sudo yum install java-11-openjdk java-11-openjdk-devel
``` ```
Centos Stream 8, Stream 9: :::
```bash :::{group-tab} CentOS Stream 8
```shell
sudo dnf install java-11-openjdk java-11-openjdk-devel sudo dnf install java-11-openjdk java-11-openjdk-devel
``` ```
:::
:::{group-tab} CentOS Stream 9
```shell
sudo dnf install java-11-openjdk java-11-openjdk-devel
```
:::
::::
## Setup ## Setup
### Download Installer ### Download Installer
@ -51,31 +65,40 @@ On your PC, navigate to the [Ignite Realtime downloads section](https://www.igni
Retrieve the file location by copying the URL from the “click here” link, depending on your browser you may have a Copy Link or similar option in your right click menu. Retrieve the file location by copying the URL from the “click here” link, depending on your browser you may have a Copy Link or similar option in your right click menu.
In the console, ensure youre in your users home directory: In the console, ensure youre in your users home directory:
```bash
```shell
cd ~ cd ~
``` ```
Download and install the package, replacing the URL with the latest you got from the Openfire download page earlier Download and install the package, replacing the URL with the latest you got from the Openfire download page earlier
Ubuntu 1804, 2004, 2204: ::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
```bash :::
wget https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_4.7.2_all.deb :::{group-tab} CentOS 7
wget <https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_4.7.2_all.deb>
dpkg -i openfire_4.7.2_all.deb dpkg -i openfire_4.7.2_all.deb
``` :::
:::{group-tab} CentOS Stream 8
Centos 7, Stream 8, Stream 9: wget <https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire-4.7.2-1.noarch.rpm>
```bash
wget https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire-4.7.2-1.noarch.rpm
yum install -y openfire-4.7.2-1.noarch.rpm yum install -y openfire-4.7.2-1.noarch.rpm
``` :::
:::{group-tab} CentOS Stream 9
wget <https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire-4.7.2-1.noarch.rpm>
yum install -y openfire-4.7.2-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:
```bash ```shell
mysql -u root -p mysql -u root -p
```
```sql
create database alliance_jabber; create database alliance_jabber;
grant all privileges on alliance_jabber . * to 'allianceserver'@'localhost'; grant all privileges on alliance_jabber . * to 'allianceserver'@'localhost';
exit; exit;
@ -83,7 +106,7 @@ exit;
### Web Configuration ### Web Configuration
The remainder of the setup occurs through Openfires web interface. Navigate to http://example.com:9090, or if youre behind CloudFlare, go straight to your servers IP:9090. The remainder of the setup occurs through Openfires web interface. Navigate to <http://example.com:9090>, or if youre behind CloudFlare, go straight to your servers IP:9090.
Select your language. I sure hope its English if youre reading this guide. Select your language. I sure hope its English if youre reading this guide.
@ -165,7 +188,7 @@ ACL is achieved by assigning groups to each of the three tiers: `Owners`, `Admin
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -6,10 +6,9 @@ In the past, access to services was dictated by a list of settings in `settings.
Instead of granting access to services by the previous rigid structure, access to services is now granted by the built in Django permissions system. This means that service access can be more granular, allowing only certain states, certain groups, for instance Corp CEOs, or even individual user access to each enabled service. Instead of granting access to services by the previous rigid structure, access to services is now granted by the built in Django permissions system. This means that service access can be more granular, allowing only certain states, certain groups, for instance Corp CEOs, or even individual user access to each enabled service.
```eval_rst :::{important}
.. important::
If you grant access to an individual user, they will have access to that service regardless of whether or not they are a member. If you grant access to an individual user, they will have access to that service regardless of whether or not they are a member.
``` :::
Each service has an access permission defined, named like `Can access the <service name> service`. Each service has an access permission defined, named like `Can access the <service name> service`.
@ -19,10 +18,9 @@ A user can be granted the same permission from multiple sources. e.g. they may h
## Removing access ## Removing access
```eval_rst :::{danger}
.. danger::
Access removal is processed immediately after removing a permission from a user or group. If you remove access from a large group, such as Member, it will immediately remove all users from that service. Access removal is processed immediately after removing a permission from a user or group. If you remove access from a large group, such as Member, it will immediately remove all users from that service.
``` :::
When you remove a service permission from a user, a signal is triggered which will activate an immediate permission check. For users this will trigger an access check for all services. For groups, due to the potential extra load, only the services whose permissions have changed will be verified, and only the users in that group. When you remove a service permission from a user, a signal is triggered which will activate an immediate permission check. For users this will trigger an access check for all services. For groups, due to the potential extra load, only the services whose permissions have changed will be verified, and only the users in that group.

View File

@ -34,7 +34,7 @@ DATABASES['phpbb3'] = {
Create a database to install phpBB3 in. Create a database to install phpBB3 in.
```bash ```shell
mysql -u root -p mysql -u root -p
create database alliance_forum; create database alliance_forum;
grant all privileges on alliance_forum . * to 'allianceserver'@'localhost'; grant all privileges on alliance_forum . * to 'allianceserver'@'localhost';
@ -51,19 +51,19 @@ In the console, navigate to your users 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
```bash ```shell
wget https://download.phpbb.com/pub/release/3.3/3.3.8/phpBB-3.3.8.zip wget https://download.phpbb.com/pub/release/3.3/3.3.8/phpBB-3.3.8.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
```bash ```shell
unzip phpBB-3.3.8.zip unzip phpBB-3.3.8.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`.
```bash ```shell
mv phpBB3 /var/www/forums mv phpBB3 /var/www/forums
``` ```
@ -72,7 +72,7 @@ The web server needs read/write permission to this folder
Apache: `chown -R www-data:www-data /var/www/forums` Apache: `chown -R www-data:www-data /var/www/forums`
Nginx: `chown -R nginx:nginx /var/www/forums` Nginx: `chown -R nginx:nginx /var/www/forums`
```eval_rst ```{eval-rst}
.. tip:: .. tip::
Nginx: Some distributions use the ``www-data:www-data`` user:group instead of ``nginx:nginx``. If you run into problems with permissions try it instead. Nginx: Some distributions use the ``www-data:www-data`` user:group instead of ``nginx:nginx``. If you run into problems with permissions try it instead.
.. ..
@ -157,7 +157,7 @@ phpBB will then write its own config file.
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
```bash ```shell
rm -rf /var/www/forums/install rm -rf /var/www/forums/install
``` ```
@ -171,7 +171,7 @@ 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
```bash ```shell
mysql -u root -p mysql -u root -p
use alliance_forum; use alliance_forum;
alter table phpbb_users change user_style user_style int not null default 1 alter table phpbb_users change user_style user_style int not null default 1
@ -187,7 +187,7 @@ Once settings have been configured, run migrations and restart Gunicorn and Cele
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -11,6 +11,7 @@ SMF requires PHP installed in your web server. Apache has `mod_php`, NGINX requi
## 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:
@ -31,44 +32,44 @@ DATABASES['smf'] = {
### 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.
Download using wget, replacing the URL with the URL for the package you just retrieved Download using wget, replacing the URL with the URL for the package you just retrieved
```bash ```shell
wget https://download.simplemachines.org/index.php?thanks;filename=smf_2-1-2_install.tar.gz wget https://download.simplemachines.org/index.php?thanks;filename=smf_2-1-2_install.tar.gz
``` ```
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
```bash
```shell
unzip smf_2-1-2_install.zip unzip smf_2-1-2_install.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`.
```bash
```shell
mv smf /var/www/forums mv smf /var/www/forums
```` ```
The web server needs read/write permission to this folder The web server needs read/write permission to this folder
Apache: `chown -R www-data:www-data /var/www/forums` Apache: `chown -R www-data:www-data /var/www/forums`
Nginx: `chown -R nginx:nginx /var/www/forums` Nginx: `chown -R nginx:nginx /var/www/forums`
```eval_rst :::{tip}
.. tip::
Nginx: Some distributions use the ``www-data:www-data`` user:group instead of ``nginx:nginx``. If you run into problems with permissions try it instead. Nginx: Some distributions use the ``www-data:www-data`` user:group instead of ``nginx:nginx``. If you run into problems with permissions try it instead.
.. :::
```
### Database Preparation ### Database Preparation
SMF needs a database. Create one: SMF needs a database. Create one:
```shell ```shell
mysql -u root -p mysql -u root -p
``` ```
```mysql ```sql
create database alliance_smf; create database alliance_smf;
grant all privileges on alliance_smf . * to 'allianceserver'@'localhost'; grant all privileges on alliance_smf . * to 'allianceserver'@'localhost';
exit; exit;
@ -81,7 +82,8 @@ Enter the database information into the `DATABASES['smf']` section of your auth
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:
```apache
```ini
<VirtualHost *:80> <VirtualHost *:80>
ServerName forums.example.com ServerName forums.example.com
DocumentRoot /var/www/forums DocumentRoot /var/www/forums
@ -92,7 +94,8 @@ A minimal Apache config might look like:
```` ````
A minimal Nginx config might look like: A minimal Nginx config might look like:
```nginx
```ini
server { server {
listen 80; listen 80;
server_name forums.example.com; server_name forums.example.com;
@ -108,7 +111,8 @@ server {
include fastcgi_params; include fastcgi_params;
} }
} }
```` ```
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
@ -120,6 +124,7 @@ 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
@ -139,7 +144,7 @@ Once settings are entered, apply migrations and restart Gunicorn and Celery.
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -38,14 +38,14 @@ To install we need a copy of the server. You can find the latest version from th
Download the server, replacing the link with the link you got earlier. Download the server, replacing the link with the link you got earlier.
``` bash ```shell
cd ~ cd ~
wget https://files.teamspeak-services.com/releases/server/3.13.7/teamspeak3-server_linux_amd64-3.13.7.tar.bz2 wget https://files.teamspeak-services.com/releases/server/3.13.7/teamspeak3-server_linux_amd64-3.13.7.tar.bz2
``` ```
Now we need to extract the file. Now we need to extract the file.
```bash ```shell
tar -xf teamspeak3-server_linux_amd64-3.13.7.tar.bz2 tar -xf teamspeak3-server_linux_amd64-3.13.7.tar.bz2
``` ```
@ -53,7 +53,7 @@ tar -xf teamspeak3-server_linux_amd64-3.13.7.tar.bz2
TeamSpeak needs its own user. TeamSpeak needs its own user.
```bash ```shell
adduser --disabled-login teamspeak adduser --disabled-login teamspeak
``` ```
@ -61,7 +61,7 @@ adduser --disabled-login teamspeak
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.
```bash ```shell
mv teamspeak3-server_linux_amd64 /usr/local/teamspeak mv teamspeak3-server_linux_amd64 /usr/local/teamspeak
chown -R teamspeak:teamspeak /usr/local/teamspeak chown -R teamspeak:teamspeak /usr/local/teamspeak
``` ```
@ -70,14 +70,14 @@ chown -R teamspeak:teamspeak /usr/local/teamspeak
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.
```bash ```shell
ln -s /usr/local/teamspeak/ts3server_startscript.sh /etc/init.d/teamspeak ln -s /usr/local/teamspeak/ts3server_startscript.sh /etc/init.d/teamspeak
update-rc.d teamspeak defaults update-rc.d teamspeak defaults
``` ```
Finally we start the server. Finally we start the server.
```bash ```shell
service teamspeak start service teamspeak start
``` ```
@ -85,7 +85,7 @@ service teamspeak start
Set your Teamspeak Serveradmin password to a random string Set your Teamspeak Serveradmin password to a random string
```bash ```shell
./ts3server_minimal_runscript.sh inifile=ts3server.ini serveradmin_password=pleasegeneratearandomstring ./ts3server_minimal_runscript.sh inifile=ts3server.ini serveradmin_password=pleasegeneratearandomstring
``` ```
@ -139,7 +139,7 @@ Then, in the top-right corner click, click on `Update TS3 Groups` to start the p
Start a django shell with: Start a django shell with:
```bash ```shell
python manage.py shell python manage.py shell
``` ```
@ -180,7 +180,7 @@ This usually occurs if you've created a separate serverquery user to use with au
To use and configure this service, users will require some of the following. To use and configure this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -47,7 +47,7 @@ Once these are entered, run migrations and restart Gunicorn and Celery.
To use this service, users will require some of the following. To use this service, users will require some of the following.
```eval_rst ```{eval-rst}
+---------------------------------------+------------------+--------------------------------------------------------------------------+ +---------------------------------------+------------------+--------------------------------------------------------------------------+
| Permission | Admin Site | Auth Site | | Permission | Admin Site | Auth Site |
+=======================================+==================+==========================================================================+ +=======================================+==================+==========================================================================+

View File

@ -7,12 +7,11 @@ Welcome to the official documentation for **Alliance Auth**!
**Alliance Auth** is a web site that helps Eve Online organizations efficiently manage access to applications and external services. **Alliance Auth** is a web site that helps Eve Online organizations efficiently manage access to applications and external services.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Contents :caption: Contents
installation/index sinstallation/index
installation-containerized/index installation-containerized/index
features/index features/index
maintenance/index maintenance/index
@ -20,4 +19,3 @@ Welcome to the official documentation for **Alliance Auth**!
customizing/index customizing/index
development/index development/index
contributing/index contributing/index
```

View File

@ -2,10 +2,9 @@
This document describes how to install **Alliance Auth** from scratch. This document describes how to install **Alliance Auth** from scratch.
```eval_rst :::{note}
.. note::
There are additional installation steps for activating services and apps that come with **Alliance Auth**. Please see the page for the respective service or apps in chapter :doc:`/features/index` for details. There are additional installation steps for activating services and apps that come with **Alliance Auth**. Please see the page for the respective service or apps in chapter :doc:`/features/index` for details.
``` :::
## Dependencies ## Dependencies
@ -15,7 +14,6 @@ Alliance Auth can be installed on any in-support *nix operating system.
Our install documentation targets the following operating systems. Our install documentation targets the following operating systems.
- Ubuntu 18.04
- Ubuntu 20.04 - Ubuntu 20.04
- Ubuntu 22.04 - Ubuntu 22.04
- Centos 7 - Centos 7
@ -28,234 +26,213 @@ To install on your favorite flavour of Linux, identify and install equivalent pa
It is recommended to ensure your OS is fully up to date before proceeding. We may also add Package Repositories here, used later in the documentation. It is recommended to ensure your OS is fully up to date before proceeding. We may also add Package Repositories here, used later in the documentation.
Ubuntu 1804, 2004, 2204: ::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
```bash ```shell
sudo apt-get update sudo apt-get update
```
```bash
sudo apt-get upgrade sudo apt-get upgrade
```
```bash
sudo do-dist-upgrade sudo do-dist-upgrade
``` ```
CentOS 7: :::
:::{group-tab} CentOS 7
```bash ```shell
yum install epel-release yum install epel-release
```
```bash
sudo yum upgrade sudo yum upgrade
``` ```
CentOS Stream 8: :::
:::{group-tab} CentOS Stream 8
```bash ```shell
sudo dnf config-manager --set-enabled powertools sudo dnf config-manager --set-enabled powertools
```
```bash
sudo dnf install epel-release epel-next-release sudo dnf install epel-release epel-next-release
```
```bash
sudo yum upgrade sudo yum upgrade
``` ```
CentOS Stream 9: :::
:::{group-tab} CentOS Stream 9
```bash ```shell
sudo dnf config-manager --set-enabled crb sudo dnf config-manager --set-enabled crb
``` sudo dnf install epel-release epel-next-release
```bash
dnf install epel-release epel-next-release
```
```bash
sudo yum upgrade sudo yum upgrade
``` ```
:::
::::
### Python ### Python
Install Python 3.10 and related tools on your system. Install Python 3.11 and related tools on your system.
Ubuntu 1804, 2004: ::::{tabs}
```bash :::{group-tab} Ubuntu 2004, 2204
```shell
sudo add-apt-repository ppa:deadsnakes/ppa sudo add-apt-repository ppa:deadsnakes/ppa
```
```bash
sudo apt-get update sudo apt-get update
sudo apt-get install python3.11 python3.11-dev python3.11-venv
``` ```
```bash :::
sudo apt-get install python3.10 python3.10-dev python3.10-venv :::{group-tab} CentOS 7
```
Ubuntu 2204:
```eval_rst
.. note::
Ubuntu 2204 ships with Python 3.10 already, but some important tools are missing in the default installation.
```
```bash
sudo apt-get install python3.10-dev python3.10-venv
```
CentOS 7:
We need to build Python from source We need to build Python from source
Centos Stream 8/9:
```eval_rst
.. note::
A Python 3.9 Package is available for Stream 8 and 9. You _may_ use this instead of building your own package. But our documentation will assume Python3.10 and you may need to substitute as necessary
sudo dnf install python39 python39-devel
```
```bash ```bash
cd ~ cd ~
```
```bash
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
``` wget https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz
tar xvf Python-3.11.5.tgz
```bash cd Python-3.11.5/
wget https://www.python.org/ftp/python/3.10.5/Python-3.10.5.tgz
```
```bash
tar xvf Python-3.10.5.tgz
```
```bash
cd Python-3.10.5/
```
```bash
./configure --enable-optimizations --enable-shared ./configure --enable-optimizations --enable-shared
sudo make altinstall
``` ```
:::
:::{group-tab} CentOS Stream 8
We need to build Python from source
```bash ```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz
tar xvf Python-3.11.5.tgz
cd Python-3.11.5/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```
:::
:::{group-tab} CentOS Stream 9
We need to build Python from source
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz
tar xvf Python-3.11.5.tgz
cd Python-3.11.5/
./configure --enable-optimizations --enable-shared
sudo make altinstall sudo make altinstall
``` ```
### Database ### Database
It's recommended to use a database service instead of SQLite. Many options are available, but this guide will use MariaDB. It's recommended to use a database service instead of SQLite. Many options are available, but this guide will use MariaDB 10.11
```eval_rst ::::{tabs}
.. note::
Ubuntu distributions prior to 20.04 come with an older version of Maria DB, which is not compatible with **Alliance Auth**. You need Maria DB 10.3 or higher!
For 20.04 we still recommend to install Maria DB from the link below in order to get the newest stable version.
For 22.04 we recommend installing from the default Ubuntu distro, since it comes with the newest stable version.
```
Ubuntu 1804, 2004: :::{group-tab} Ubuntu 2004, 2204
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=20.04+%22focal%22&v=10.11&r_m=osuosl> to add the MariaDB repository to your host.
```eval_rst ```shell
.. warning::
Please follow these steps to update MariaDB
https://mariadb.org/download/?t=repo-config&d=20.04+%22focal%22&v=10.6&r_m=osuosl
```
Ubuntu 1804, 2004, 2204
```bash
sudo apt-get install mariadb-server mariadb-client libmysqlclient-dev sudo apt-get install mariadb-server mariadb-client libmysqlclient-dev
``` ```
CentOS 7: :::
:::{group-tab} CentOS 7
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=CentOS+7&v=10.11&r_m=osuosl> to add the MariaDB repository to your host.
```eval_rst ```shell
.. warning::
Please follow these steps to update MariaDB
https://mariadb.org/download/?t=repo-config&d=CentOS+7+%28x86_64%29&v=10.6&r_m=osuosl
```
```bash
sudo yum install MariaDB-server MariaDB-client MariaDB-devel MariaDB-shared sudo yum install MariaDB-server MariaDB-client MariaDB-devel MariaDB-shared
``` ```
CentOS Stream 8/9: :::
:::{group-tab} CentOS Stream 8
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=CentOS+Stream&v=10.11&r_m=osuosl> to add the MariaDB repository to your host.
```eval_rst ```shell
.. note::
We recommend using the built in AppStream, as they are maintained by CentOS. Currently an AppStream is not available for 10.6
```
```bash
sudo dnf module enable mariadb:10.5
```
```bash
sudo dnf install mariadb mariadb-server mariadb-devel sudo dnf install mariadb mariadb-server mariadb-devel
``` ```
```bash :::
sudo systemctl enable mariadb :::{group-tab} CentOS Stream 9
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=CentOS+Stream&v=10.11&r_m=osuosl> to add the MariaDB repository to your host.
```shell
sudo dnf install mariadb mariadb-server mariadb-devel
``` ```
```bash :::
sudo systemctl start mariadb ::::
```
```eval_rst :::::{important}
.. important:: ::::{tabs}
If you don't plan on running the database on the same server as auth you still need to install the ``libmysqlclient-dev`` package on Ubuntu or ``mariadb-devel`` package on CentOS. :::{group-tab} Ubuntu 2004, 2204
``` If you don't plan on running the database on the same server as auth you still need to install the `libmysqlclient-dev` package
:::
:::{group-tab} CentOS 7
If you don't plan on running the database on the same server as auth you still need to install the `mariadb-devel` package
:::
:::{group-tab} CentOS Stream 8
If you don't plan on running the database on the same server as auth you still need to install the `mariadb-devel` package
:::
:::{group-tab} CentOS Stream 9
If you don't plan on running the database on the same server as auth you still need to install the `mariadb-devel` package
:::
::::
:::::
### Redis and Other Tools ### Redis and Other Tools
A few extra utilities are also required for installation of packages. A few extra utilities are also required for installation of packages.
Ubuntu 1804, 2004, 2204: ::::{tabs}
```bash :::{group-tab} Ubuntu 2004, 2204
```shell
sudo apt-get install unzip git redis-server curl libssl-dev libbz2-dev libffi-dev build-essential pkg-config sudo apt-get install unzip git redis-server curl libssl-dev libbz2-dev libffi-dev build-essential pkg-config
``` ```
CentOS 7: :::
:::{group-tab} CentOS 7
```bash ```shell
sudo yum install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget pkg-config sudo yum install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget pkg-config
``` ```
```bash ```shell
sudo systemctl enable redis.service sudo systemctl enable redis.service
```
```bash
sudo systemctl start redis.service sudo systemctl start redis.service
``` ```
CentOS Stream 8, Stream 9: :::
:::{group-tab} CentOS Stream 8
```bash ```shell
sudo dnf install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget sudo dnf install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget
``` ```
```bash ```shell
sudo systemctl enable redis.service sudo systemctl enable redis.service
```
```bash
sudo systemctl start redis.service sudo systemctl start redis.service
``` ```
:::
:::{group-tab} CentOS Stream 9
```shell
sudo dnf install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget
```
```shell
sudo systemctl enable redis.service
sudo systemctl start redis.service
```
:::
::::
## Database Setup ## Database Setup
Alliance Auth needs a MySQL user account and database. Open an SQL shell with Alliance Auth needs a MySQL user account and database. Open an SQL shell with
```bash ```shell
sudo mysql -u root sudo mysql -u root
``` ```
@ -271,22 +248,24 @@ 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 ```shell
mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -u root mysql mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -u root mysql
``` ```
```eval_rst :::{note}
.. note:: You may see errors when you add the timezone tables. To make sure that they were correctly added run the following commands and check for the ``time_zone`` tables
You may see errors when you add the timezone tables. To make sure that they were correctly added run the following commands and check for the ``time_zone`` tables::
```shell
mysql -u root -p mysql -u root -p
use mysql; use mysql;
show tables; show tables;
``` ```
:::
Close the SQL shell and secure your database server with this command: Close the SQL shell and secure your database server with this command:
```bash ```shell
mysql_secure_installation mysql_secure_installation
``` ```
@ -295,86 +274,96 @@ mysql_secure_installation
### User Account ### User Account
For security and permissions, its highly recommended you create a separate user to install auth under. Do not log in as this account. For security and permissions, its highly recommended you create a separate user to install auth under. Do not log in as this account.
::::{tabs}
Ubuntu 1804, 2004, 2204: :::{group-tab} Ubuntu 2004, 2204
```bash ```shell
sudo adduser --disabled-login allianceserver
```
CentOS 7, Stream 8, Stream 9:
```bash
sudo useradd -s /bin/bash allianceserver sudo useradd -s /bin/bash allianceserver
``` ```
```bash :::
:::{group-tab} CentOS 7
```shell
sudo passwd -l allianceserver sudo passwd -l allianceserver
``` ```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo passwd -l allianceserver
```
:::
:::{group-tab} CentOS Stream 9
```shell
sudo passwd -l allianceserver
```
:::
::::
### Prepare Directories ### Prepare Directories
```bash ```shell
sudo mkdir -p /var/www/myauth/static sudo mkdir -p /var/www/myauth/static
``` ```
```bash ```shell
sudo chown -R allianceserver:allianceserver /var/www/myauth/static/ sudo chown -R allianceserver:allianceserver /var/www/myauth/static/
``` ```
```eval_rst :::{warning}
.. note:: When installing and performing maintenance on Alliance Auth, virtual environments and python packages, _sudo_ means _superuser_ _do_, this will not use your venv or your allianceserver user and will routinely break your permission structure.
When installing and performing maintenance on Alliance Auth, using the allianceserver user will greatly simplify permission management::
Only use sudo for _system_ management or if you are unsure, when explicitly instructed to do so.
```shell
sudo su allianceserver sudo su allianceserver
``` ```
:::
### Virtual Environment ### Virtual Environment
Switch to the allianceserver user. Switch to the allianceserver user.
```bash ```shell
sudo su allianceserver sudo su allianceserver
``` ```
And switch to it's home directory: And switch to it's home directory:
```bash ```shell
cd cd ~
```
```eval_rst
.. note::
In general using the allianceserver user will greatly simplify permission management, when installing and performing maintenance on Alliance Auth.
``` ```
Create a Python virtual environment and put it somewhere convenient (e.g. `/home/allianceserver/venv/auth/`) Create a Python virtual environment and put it somewhere convenient (e.g. `/home/allianceserver/venv/auth/`)
```eval_rst :::{note}
.. note::
Your python3.x command/version may vary depending on your installed python version. Your python3.x command/version may vary depending on your installed python version.
:::
```shell
python3.11 -m venv /home/allianceserver/venv/auth/
``` ```
```bash :::{tip}
python3.10 -m venv /home/allianceserver/venv/auth/ A virtual environment provides support for creating a lightweight "copy" of Python with their own site directories. Each virtual environment has its own Python binary (allowing creation of environments with various Python versions) and can have its own independent set of installed Python packages in its site directories. You can read more about virtual environments on the Python_ docs. <https://docs.python.org/3/library/venv.html>
``` :::
```eval_rst
.. tip::
A virtual environment provides support for creating a lightweight "copy" of Python with their own site directories. Each virtual environment has its own Python binary (allowing creation of environments with various Python versions) and can have its own independent set of installed Python packages in its site directories. You can read more about virtual environments on the Python_ docs.
.. _Python: https://docs.python.org/3/library/venv.html
```
Activate the virtual environment with (Note the `/bin/activate` on the end of the path): Activate the virtual environment with (Note the `/bin/activate` on the end of the path):
```bash ```shell
source /home/allianceserver/venv/auth/bin/activate source /home/allianceserver/venv/auth/bin/activate
``` ```
```eval_rst :::{hint}
.. hint::
Each time you come to do maintenance on your Alliance Auth installation, you should activate your virtual environment first. When finished, deactivate it with the ``deactivate`` command. Each time you come to do maintenance on your Alliance Auth installation, you should activate your virtual environment first. When finished, deactivate it with the ``deactivate`` command.
``` :::
### Eve Online SSO ### Eve Online SSO
@ -386,22 +375,21 @@ As **callback URL** you want to define the URL of your Alliance Auth site plus t
### Alliance Auth Project ### Alliance Auth Project
```eval_rst :::{warning}
.. warning::
Before installing any Python packages please double-check that you have activated in the virtual environment. This is usually indicated by your command line in the terminal starting with: `(auth)`. Before installing any Python packages please double-check that you have activated in the virtual environment. This is usually indicated by your command line in the terminal starting with: `(auth)`.
``` :::
#### Install Python packages #### Install Python packages
Update & install basic tools before installing further Python packages: Update & install basic tools before installing further Python packages:
```bash ```shell
pip install -U pip setuptools wheel pip install -U pip setuptools wheel
``` ```
You can install **Alliance Auth** with the following command. This will install AA, AA's Python dependencies, superlance for memory monitoring and gunicorn as a wsgi server You can install **Alliance Auth** with the following command. This will install AA, AA's Python dependencies, superlance for memory monitoring and gunicorn as a wsgi server
```bash ```shell
pip install allianceauth superlance gunicorn pip install allianceauth superlance gunicorn
``` ```
@ -409,13 +397,13 @@ pip install allianceauth superlance gunicorn
Now you need to create the Django project that will run **Alliance Auth**. Ensure you are in the allianceserver home directory by issuing: Now you need to create the Django project that will run **Alliance Auth**. Ensure you are in the allianceserver home directory by issuing:
```bash ```shell
cd /home/allianceserver cd /home/allianceserver
``` ```
The following command bootstraps a Django project which will run your **Alliance Auth** instance. You can rename it from `myauth` to anything you'd like. Note that this name is shown by default as the site name but that can be changed later. The following command bootstraps a Django project which will run your **Alliance Auth** instance. You can rename it from `myauth` to anything you'd like. Note that this name is shown by default as the site name but that can be changed later.
```bash ```shell
allianceauth start myauth allianceauth start myauth
``` ```
@ -423,7 +411,7 @@ allianceauth start myauth
Your settings file needs configuring: Your settings file needs configuring:
```bash ```shell
nano myauth/myauth/settings/local.py nano myauth/myauth/settings/local.py
``` ```
@ -439,34 +427,36 @@ nano myauth/myauth/settings/local.py
Django needs to setup the database before it can start. Django needs to setup the database before it can start.
```bash ```shell
python /home/allianceserver/myauth/manage.py migrate python /home/allianceserver/myauth/manage.py migrate
``` ```
Now we need to round up all the static files required to render templates. Make a directory to serve them from and populate it. Now we need to round up all the static files required to render templates. Make a directory to serve them from and populate it.
```bash ```shell
python /home/allianceserver/myauth/manage.py collectstatic --noinput python /home/allianceserver/myauth/manage.py collectstatic --noinput
``` ```
Check to ensure your settings are valid. Check to ensure your settings are valid.
```bash ```shell
python /home/allianceserver/myauth/manage.py check python /home/allianceserver/myauth/manage.py check
``` ```
```eval_rst :::{hint}
.. hint::
If you are using root, ensure the allianceserver user has read/write permissions to this directory before proceeding:: If you are using root, ensure the allianceserver user has read/write permissions to this directory before proceeding::
```shell
chown -R allianceserver:allianceserver /home/allianceserver/myauth chown -R allianceserver:allianceserver /home/allianceserver/myauth
``` ```
:::
#### Setup superuser #### Setup 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 ```shell
python /home/allianceserver/myauth/manage.py createsuperuser python /home/allianceserver/myauth/manage.py createsuperuser
``` ```
@ -488,72 +478,117 @@ The default configuration is good enough for most installations. Additional info
[Supervisor](http://supervisord.org/) is a process watchdog service: it makes sure other processes are started automatically and kept running. It can be used to automatically start the WSGI server and Celery workers for background tasks. [Supervisor](http://supervisord.org/) is a process watchdog service: it makes sure other processes are started automatically and kept running. It can be used to automatically start the WSGI server and Celery workers for background tasks.
```eval_rst :::{note}
.. note::
You will need to exit the allianceserver user back to a user with sudo capabilities to install supervisor:: You will need to exit the allianceserver user back to a user with sudo capabilities to install supervisor::
```shell
exit exit
``` ```
Ubuntu 1804, 2004, 2204: :::
```bash ::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
```shell
sudo apt-get install supervisor sudo apt-get install supervisor
``` ```
CentOS 7: :::
:::{group-tab} CentOS 7
```bash ```shell
sudo dnf install supervisor sudo dnf install supervisor
``` ```
```bash ```shell
sudo systemctl enable supervisord.service sudo systemctl enable supervisord.service
``` ```
```bash ```shell
sudo systemctl start supervisord.service sudo systemctl start supervisord.service
``` ```
CentOS Stream 8, Stream 9: :::
:::{group-tab} CentOS Stream 8
```bash ```shell
sudo dnf install supervisor sudo dnf install supervisor
``` ```
```bash ```shell
sudo systemctl enable supervisord.service sudo systemctl enable supervisord.service
``` ```
```bash ```shell
sudo systemctl start supervisord.service sudo systemctl start supervisord.service
``` ```
:::
:::{group-tab} CentOS Stream 9
```shell
sudo dnf install supervisor
```
```shell
sudo systemctl enable supervisord.service
```
```shell
sudo 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.
::::{tabs}
Ubuntu 1804, 2004: :::{group-tab} Ubuntu 2004, 2204
```bash ```shell
ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisor/conf.d/myauth.conf ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisor/conf.d/myauth.conf
``` ```
CentOS: :::
:::{group-tab} CentOS 7
```bash ```shell
sudo ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini sudo ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
``` ```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
```
:::
:::{group-tab} CentOS Stream 9
```shell
sudo ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
```
:::
::::
Activate it with `sudo supervisorctl reload`. Activate it with `sudo supervisorctl reload`.
You can check the status of the processes with `sudo 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 `sudo supervisorctl status`. Logs from these processes are available in `/home/allianceserver/myauth/log` named by process.
```eval_rst :::{note}
.. note::
Any time the code or your settings change you'll need to restart Gunicorn and Celery. :: Any time the code or your settings change you'll need to restart Gunicorn and Celery. ::
```shell
sudo supervisorctl restart myauth: sudo supervisorctl restart myauth:
``` ```
:::
## Web server ## Web server
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.
@ -566,42 +601,42 @@ Periodically [new releases](https://gitlab.com/allianceauth/allianceauth/tags) a
To update your install, swap to your allianceserver user To update your install, swap to your allianceserver user
```bash ```shell
sudo su allianceserver sudo su allianceserver
``` ```
Activate your virtual environment Activate your virtual environment
```bash ```shell
source /home/allianceserver/venv/auth/bin/activate source /home/allianceserver/venv/auth/bin/activate
``` ```
and update with: and update with:
```bash ```shell
pip install -U allianceauth pip install -U allianceauth
``` ```
Some releases come with changes to the base settings. Update your project's settings with: Some releases come with changes to the base settings. Update your project's settings with:
```bash ```shell
allianceauth update /home/allianceserver/myauth allianceauth update /home/allianceserver/myauth
``` ```
Some releases come with new or changed models. Update your database to reflect this with: Some releases come with new or changed models. Update your database to reflect this with:
```bash ```shell
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 ```shell
python /home/allianceserver/myauth/manage.py collectstatic --noinput python /home/allianceserver/myauth/manage.py collectstatic --noinput
``` ```
Always restart AA, Celery and Gunicorn after updating: Always restart AA, Celery and Gunicorn after updating:
```bash ```shell
supervisorctl restart myauth: supervisorctl restart myauth:
``` ```

View File

@ -8,68 +8,115 @@ If you're using a small VPS to host services with very limited memory, consider
## Installation ## Installation
Ubuntu 1804, 2004: ::::{tabs}
```bash
:::{group-tab} Ubuntu 2004, 2204
```shell
apt-get install apache2 apt-get install apache2
``` ```
:::
CentOS 7: :::{group-tab} CentOS 7
```bash ```shell
yum install httpd yum install httpd
``` ```
Centos Stream 8, Stream 9 :::
```bash :::{group-tab} CentOS Stream 8
```shell
dnf install httpd dnf install httpd
``` ```
:::
CentOS 7, Stream 8, Stream 9 :::{group-tab} CentOS Stream 9
```bash ```shell
systemctl enable httpd systemctl enable httpd
```
```bash
systemctl start httpd systemctl start httpd
``` ```
:::
::::
CentOS 7, Stream 8, Stream 9
## Configuration ## Configuration
### Permissions
Apache needs to be able to read the folder containing your auth project's static files. Apache needs to be able to read the folder containing your auth project's static files.
Ubuntu 1804, 2004:
``` ::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
```shell
chown -R www-data:www-data /var/www/myauth/static chown -R www-data:www-data /var/www/myauth/static
``` ```
CentOS 7, Stream 8, Stream 9
``` :::
:::{group-tab} CentOS 7
```shell
chown -R apache:apache /var/www/myauth/static chown -R apache:apache /var/www/myauth/static
``` ```
:::
:::{group-tab} CentOS Stream 8
```shell
chown -R apache:apache /var/www/myauth/static
```
:::
:::{group-tab} CentOS Stream 9
```shell
chown -R apache:apache /var/www/myauth/static
```
:::
::::
### Further Configuration
Apache serves sites through defined virtual hosts. These are located in `/etc/apache2/sites-available/` on Ubuntu and `/etc/httpd/conf.d/httpd.conf` on CentOS. Apache serves sites through defined virtual hosts. These are located in `/etc/apache2/sites-available/` on Ubuntu and `/etc/httpd/conf.d/httpd.conf` on CentOS.
A virtual host for auth need only proxy requests to your WSGI server (Gunicorn if you followed the install guide) and serve static files. Examples can be found below. Create your config in its own file e.g. `myauth.conf` A virtual host for auth need only proxy requests to your WSGI server (Gunicorn if you followed the install guide) and serve static files. Examples can be found below. Create your config in its own file e.g. `myauth.conf`
### Ubuntu ::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
To proxy and modify headers a few mods need to be enabled. To proxy and modify headers a few mods need to be enabled.
```bash
```shell
a2enmod proxy a2enmod proxy
a2enmod proxy_http a2enmod proxy_http
a2enmod headers a2enmod headers
``` ```
Create a new config file for auth e.g. `/etc/apache2/sites-available/myauth.conf` and fill out the virtual host configuration. To enable your config use `a2ensite myauth.conf` and then reload apache with `service apache2 reload`. Create a new config file for auth e.g. `/etc/apache2/sites-available/myauth.conf` and fill out the virtual host configuration. To enable your config use `a2ensite myauth.conf` and then reload apache with `service apache2 reload`.
:::
:::{group-tab} CentOS 7
Place your virtual host configuration in the appropriate section within `/etc/httpd/conf.d/httpd.conf` and restart the httpd service with `systemctl restart httpd`.
:::
:::{group-tab} CentOS Stream 8
Place your virtual host configuration in the appropriate section within `/etc/httpd/conf.d/httpd.conf` and restart the httpd service with `systemctl restart httpd`.
:::
:::{group-tab} CentOS Stream 9
Place your virtual host configuration in the appropriate section within `/etc/httpd/conf.d/httpd.conf` and restart the httpd service with `systemctl restart httpd`.
:::
::::
```eval_rst :::{warning}
.. warning:: In some scenarios, the Apache default page is still enabled. To disable it use
In some scenarios, the Apache default page is still enabled. To disable it use::
```shell
a2dissite 000-default.conf a2dissite 000-default.conf
``` ```
### CentOS :::
Place your virtual host configuration in the appropriate section within `/etc/httpd/conf.d/httpd.conf` and restart the httpd service with `systemctl restart httpd`. ### CentOS
## Sample Config File ## Sample Config File
``` ```ini
<VirtualHost *:80> <VirtualHost *:80>
ServerName auth.example.com ServerName auth.example.com
@ -107,7 +154,7 @@ It's 2018 - there's no reason to run a site without SSL. The EFF provides free,
After acquiring SSL the config file needs to be adjusted. Add the following lines inside the `<VirtualHost>` block: After acquiring SSL the config file needs to be adjusted. Add the following lines inside the `<VirtualHost>` block:
``` ```ini
RequestHeader set X-FORWARDED-PROTOCOL https RequestHeader set X-FORWARDED-PROTOCOL https
RequestHeader set X-FORWARDED-SSL On RequestHeader set X-FORWARDED-SSL On
``` ```

View File

@ -6,23 +6,21 @@ If you find Apache's `mod_wsgi` to be a headache or want to use NGINX (or some o
Check out the full [Gunicorn docs](http://docs.gunicorn.org/en/latest/index.html). Check out the full [Gunicorn docs](http://docs.gunicorn.org/en/latest/index.html).
```eval_rst :::{note}
.. note::
The page contains additional steps on how to setup and configure Gunicorn that are not required for users who decide to stick with the default Gunicorn configuration as described in the main installation guide for AA. The page contains additional steps on how to setup and configure Gunicorn that are not required for users who decide to stick with the default Gunicorn configuration as described in the main installation guide for AA.
``` :::
## Setting up Gunicorn ## Setting up Gunicorn
```eval_rst :::{note}
.. note::
If you're using a virtual environment, activate it now:: If you're using a virtual environment, activate it now::
sudo su allianceserver sudo su allianceserver
source /home/allianceserver/venv/auth/bin/activate source /home/allianceserver/venv/auth/bin/activate
``` :::
Install Gunicorn using pip Install Gunicorn using pip
```bash ```shell
pip install gunicorn pip install gunicorn
``` ```
@ -38,7 +36,7 @@ If you are following this guide, we already use [Supervisor](allianceauth.md#sup
You'll want to edit `/etc/supervisor/conf.d/myauth.conf` (or whatever you want to call the config file) You'll want to edit `/etc/supervisor/conf.d/myauth.conf` (or whatever you want to call the config file)
```text ```ini
[program:gunicorn] [program:gunicorn]
user = allianceserver user = allianceserver
directory=/home/allianceserver/myauth/ directory=/home/allianceserver/myauth/
@ -49,6 +47,7 @@ autostart=true
autorestart=true autorestart=true
stopsignal=INT stopsignal=INT
``` ```
- `[program:gunicorn]` - Change `gunicorn` to whatever you wish to call your process in Supervisor. - `[program:gunicorn]` - Change `gunicorn` to whatever you wish to call your process in Supervisor.
- `user = allianceserver` - Change to whatever user you wish Gunicorn to run as. You could even set this as allianceserver if you wished. I'll leave the question security of that up to you. - `user = allianceserver` - Change to whatever user you wish Gunicorn to run as. You could even set this as allianceserver if you wished. I'll leave the question security of that up to you.
- `directory=/home/allianceserver/myauth/` - Needs to be the path to your Alliance Auth project. - `directory=/home/allianceserver/myauth/` - Needs to be the path to your Alliance Auth project.
@ -81,6 +80,7 @@ Following this guide, you are running with a virtual environment. Therefore you'
e.g. `command=/path/to/venv/bin/gunicorn myauth.wsgi` e.g. `command=/path/to/venv/bin/gunicorn myauth.wsgi`
The example config is using the myauth venv from the main installation guide: The example config is using the myauth venv from the main installation guide:
```ini ```ini
command=/home/allianceserver/venv/auth/bin/gunicorn myauth.wsgi command=/home/allianceserver/venv/auth/bin/gunicorn myauth.wsgi
``` ```
@ -97,6 +97,6 @@ Any web server capable of proxy passing should be able to sit in front of Gunico
In the past when you made changes you restarted the entire Apache server. This is no longer required. When you update or make configuration changes that ask you to restart Apache, instead you can just restart Gunicorn: In the past when you made changes you restarted the entire Apache server. This is no longer required. When you update or make configuration changes that ask you to restart Apache, instead you can just restart Gunicorn:
```bash ```shell
supervisorctl restart myauth:gunicorn supervisorctl restart myauth:gunicorn
``` ```

View File

@ -4,8 +4,7 @@ This chapter contains the main installation guides for **Alliance Auth**.
In addition to main guide for installation Alliance Auth you also find guides for configuring web servers (Apache, NGINX) and the recommended WSGI server (Gunicorn). In addition to main guide for installation Alliance Auth you also find guides for configuring web servers (Apache, NGINX) and the recommended WSGI server (Gunicorn).
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
allianceauth allianceauth
@ -14,4 +13,4 @@ In addition to main guide for installation Alliance Auth you also find guides fo
gunicorn gunicorn
upgrade_python upgrade_python
switch_to_non_root switch_to_non_root
``` :::

View File

@ -14,7 +14,7 @@ If you're converting from Apache, here are some things to consider.
Nginx is lightweight for a reason. It doesn't try to do everything internally and instead concentrates on just being a good HTTP server. This means that, unlike Apache, it won't automatically run PHP scripts via mod_php and doesn't have an internal WSGI server like mod_wsgi. That doesn't mean that it can't, just that it relies on external processes to run these instead. This might be good or bad depending on your outlook. It's good because it allows you to segment your applications, restarting Alliance Auth wont impact your PHP applications. On the other hand it means more config and more management of services. For some people it will be worth it, for others losing the centralised nature of Apache may not be worth it. Nginx is lightweight for a reason. It doesn't try to do everything internally and instead concentrates on just being a good HTTP server. This means that, unlike Apache, it won't automatically run PHP scripts via mod_php and doesn't have an internal WSGI server like mod_wsgi. That doesn't mean that it can't, just that it relies on external processes to run these instead. This might be good or bad depending on your outlook. It's good because it allows you to segment your applications, restarting Alliance Auth wont impact your PHP applications. On the other hand it means more config and more management of services. For some people it will be worth it, for others losing the centralised nature of Apache may not be worth it.
```eval_rst ```{eval-rst}
+-----------+----------------------------------------+ +-----------+----------------------------------------+
| Apache | Nginx Replacement | | Apache | Nginx Replacement |
+===========+========================================+ +===========+========================================+
@ -22,7 +22,6 @@ Nginx is lightweight for a reason. It doesn't try to do everything internally an
+-----------+----------------------------------------+ +-----------+----------------------------------------+
| mod_wsgi | Gunicorn or other external WSGI server | | mod_wsgi | Gunicorn or other external WSGI server |
+-----------+----------------------------------------+ +-----------+----------------------------------------+
``` ```
Your .htaccess files won't work. Nginx has a separate way of managing access to folders via the server config. Everything you can do with htaccess files you can do with Nginx config. [Read more on the Nginx wiki](https://www.nginx.com/resources/wiki/start/topics/examples/likeapache-htaccess/) Your .htaccess files won't work. Nginx has a separate way of managing access to folders via the server config. Everything you can do with htaccess files you can do with Nginx config. [Read more on the Nginx wiki](https://www.nginx.com/resources/wiki/start/topics/examples/likeapache-htaccess/)
@ -33,36 +32,51 @@ Install Nginx via your preferred package manager or other method. If you need he
Nginx needs to be able to read the folder containing your auth project's static files. `chown -R nginx:nginx /var/www/myauth/static`. Nginx needs to be able to read the folder containing your auth project's static files. `chown -R nginx:nginx /var/www/myauth/static`.
```eval_rst :::{tip}
.. tip::
Some specific distros may use ``www-data:www-data`` instead of ``nginx:nginx``, causing static files (images, stylesheets etc) not to appear. You can confirm what user Nginx will run under by checking either its base config file ``/etc/nginx/nginx.conf`` for the "user" setting, or once Nginx has started ``ps aux | grep nginx``. Some specific distros may use ``www-data:www-data`` instead of ``nginx:nginx``, causing static files (images, stylesheets etc) not to appear. You can confirm what user Nginx will run under by checking either its base config file ``/etc/nginx/nginx.conf`` for the "user" setting, or once Nginx has started ``ps aux | grep nginx``.
Adjust your chown commands to the correct user if needed. Adjust your chown commands to the correct user if needed.
.. :::
```
You will need to have [Gunicorn](gunicorn.md) or some other WSGI server setup for hosting Alliance Auth. You will need to have [Gunicorn](gunicorn.md) or some other WSGI server setup for hosting Alliance Auth.
## Install ## Install
Ubuntu 1804, 2004, 2204: ::::{tabs}
```bash :::{group-tab} Ubuntu 2004, 2204
```shell
sudo apt-get install nginx sudo apt-get install nginx
``` ```
CentOS 7 :::
```bash :::{group-tab} CentOS 7
```shell
sudo yum install nginx sudo yum install nginx
``` ```
CentOS Stream 8, Stream 9: :::
```bash :::{group-tab} CentOS Stream 8
```shell
sudo dnf install nginx sudo dnf install nginx
``` ```
:::
:::{group-tab} CentOS Stream 9
```shell
sudo dnf install nginx
```
:::
::::
Create a config file in `/etc/nginx/sites-available` (`/etc/nginx/conf.d` on CentOS) and call it `alliance-auth.conf` or whatever your preferred name is. Create a config file in `/etc/nginx/sites-available` (`/etc/nginx/conf.d` on CentOS) and call it `alliance-auth.conf` or whatever your preferred name is.
Create a symbolic link to enable the site (not needed on CentOS): Create a symbolic link to enable the site (not needed on CentOS):
```bash
```shell
ln -s /etc/nginx/sites-available/alliance-auth.conf /etc/nginx/sites-enabled/ ln -s /etc/nginx/sites-available/alliance-auth.conf /etc/nginx/sites-enabled/
``` ```
@ -70,8 +84,7 @@ ln -s /etc/nginx/sites-available/alliance-auth.conf /etc/nginx/sites-enabled/
Copy this basic config into your config file. Make whatever changes you feel are necessary. Copy this basic config into your config file. Make whatever changes you feel are necessary.
```ini
```
server { server {
listen 80; listen 80;
listen [::]:80; listen [::]:80;
@ -107,7 +120,7 @@ With [Let's Encrypt](https://letsencrypt.org/) offering free SSL certificates, t
Your config will need a few additions once you've got your certificate. Your config will need a few additions once you've got your certificate.
``` ```ini
listen 443 ssl http2; # Replace listen 80; with this listen 443 ssl http2; # Replace listen 80; with this
listen [::]:443 ssl http2; # Replace listen [::]:80; with this listen [::]:443 ssl http2; # Replace listen [::]:80; with this
@ -123,7 +136,7 @@ Your config will need a few additions once you've got your certificate.
If you want to redirect all your non-SSL visitors to your secure site, below your main configs `server` block, add the following: If you want to redirect all your non-SSL visitors to your secure site, below your main configs `server` block, add the following:
``` ```ini
server { server {
listen 80; listen 80;
listen [::]:80; listen [::]:80;

View File

@ -4,10 +4,9 @@ This guide describes how to upgrade an existing Alliance Auth (AA) installation
This guide shares many similarities with the Alliance Auth install guide, but it is targeted towards existing installs needing to update. This guide shares many similarities with the Alliance Auth install guide, but it is targeted towards existing installs needing to update.
```eval_rst :::{note}
.. note::
This guide will upgrade the software components only but not change any data or configuration. This guide will upgrade the software components only but not change any data or configuration.
``` :::
## Install a new Python version ## Install a new Python version
@ -15,77 +14,84 @@ To run AA with a newer Python 3 version than your system's default you need to i
To install other Python versions than those included with your distribution, you need to add a new installation repository. Then you can install the specific Python 3 to your system. To install other Python versions than those included with your distribution, you need to add a new installation repository. Then you can install the specific Python 3 to your system.
Ubuntu 1804, 2004: :::{note}
```eval_rst
.. note::
Ubuntu 2204 ships with Python 3.10 already Ubuntu 2204 ships with Python 3.10 already
``` :::
```bash
sudo add-apt-repository ppa:deadsnakes/ppa
```
```bash
sudo apt-get update
```
```bash
sudo apt-get install python3.10 python3.10-dev python3.10-venv
```
CentOS 7:
We need to build Python from source
Centos Stream 8/9: Centos Stream 8/9:
```eval_rst :::{note}
.. note:: A Python 3.9 Package is available for Stream 8 and 9. You _may_ use this instead of building your own package. But our documentation will assume Python3.11 and you may need to substitute as neccessary
A Python 3.9 Package is available for Stream 8 and 9. You _may_ use this instead of building your own package. But our documentation will assume Python3.10 and you may need to substitute as neccessary
sudo dnf install python39 python39-devel sudo dnf install python39 python39-devel
:::
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
```shell
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
sudo apt-get install python3.11 python3.11-dev python3.11-venv
``` ```
:::
:::{group-tab} CentOS 7
```bash ```bash
cd ~ cd ~
```
```bash
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
``` wget https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz
tar xvf Python-3.11.5.tgz
```bash cd Python-3.11.5/
wget https://www.python.org/ftp/python/3.10.5/Python-3.10.5.tgz
```
```bash
tar xvf Python-3.10.5.tgz
```
```bash
cd Python-3.10.5/
```
```bash
./configure --enable-optimizations --enable-shared ./configure --enable-optimizations --enable-shared
```
```bash
sudo make altinstall sudo make altinstall
``` ```
:::
:::{group-tab} CentOS Stream 8
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz
tar xvf Python-3.11.5.tgz
cd Python-3.11.5/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```
:::
:::{group-tab} CentOS Stream 9
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.5/Python-3.11.5.tgz
tar xvf Python-3.11.5.tgz
cd Python-3.11.5/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```
:::
::::
## Preparing your venv ## Preparing your venv
Before updating your venv it is important to make sure that your current installation is stable. Otherwise your new venv might not be consistent with your data, which might create problems. Before updating your venv it is important to make sure that your current installation is stable. Otherwise your new venv might not be consistent with your data, which might create problems.
Start by navigating to your main project folder (the one that has `manage.py` in it). If you followed the default installation the path is: `/home/allianceserver/myauth` Start by navigating to your main project folder (the one that has `manage.py` in it). If you followed the default installation the path is: `/home/allianceserver/myauth`
```eval_rst :::{note}
.. note::
If you installed Alliance Auth under the allianceserver user, as reccommended. Remember to switch users for easier permission management:: If you installed Alliance Auth under the allianceserver user, as reccommended. Remember to switch users for easier permission management::
:::
```bash
sudo su allianceserver sudo su allianceserver
``` ```
Activate your venv: Activate your venv:
```bash ```shell
source /home/allianceserver/venv/auth/bin/activate source /home/allianceserver/venv/auth/bin/activate
``` ```
@ -93,23 +99,23 @@ source /home/allianceserver/venv/auth/bin/activate
Make sure to upgrade AA to the newest version: Make sure to upgrade AA to the newest version:
```bash ```shell
pip install -U allianceauth pip install -U allianceauth
``` ```
Run migrations and collectstatic. Run migrations and collectstatic.
```bash ```shell
python manage.py migrate python manage.py migrate
``` ```
```bash ```shell
python manage.py collectstatic python manage.py collectstatic
``` ```
Restart your AA supervisor: Restart your AA supervisor:
```bash ```shell
supervisorctl restart myauth: supervisorctl restart myauth:
``` ```
@ -119,38 +125,39 @@ You also need to upgrade all additional apps to their newest version that you ha
If you unsure which apps you have installed from repos check `INSTALLED_APPS` in your settings. Alternatively run this command to get a list all apps in your venv. If you unsure which apps you have installed from repos check `INSTALLED_APPS` in your settings. Alternatively run this command to get a list all apps in your venv.
```bash ```shell
pip list pip list
``` ```
Repeat as needed for your apps Repeat as needed for your apps
```bash ```shell
pip install -U APP_NAME pip install -U APP_NAME
``` ```
Make sure to run migrations and collect static files for all upgraded apps. Make sure to run migrations and collect static files for all upgraded apps.
```bash ```shell
python manage.py migrate python manage.py migrate
``` ```
```bash ```shell
python manage.py collectstatic python manage.py collectstatic
``` ```
### Restart and final check ### Restart and final check
Do a final restart of your AA supervisors and make sure your installation is still running normally. Do a final restart of your AA supervisors and make sure your installation is still running normally.
For a final check that they are no issues - e.g. any outstanding migrations - run this command: For a final check that they are no issues - e.g. any outstanding migrations - run this command:
```bash ```shell
python manage.py check python manage.py check
``` ```
If you get the following result you are good to go. Otherwise make sure to fix any issues first before proceeding. If you get the following result you are good to go. Otherwise make sure to fix any issues first before proceeding.
```bash ```shell
System check identified no issues (0 silenced). System check identified no issues (0 silenced).
``` ```
@ -160,7 +167,7 @@ Make sure you are in your venv!
First we create a list of all installed packages in your venv. You can use this list later as reference to see what packages should be installed. First we create a list of all installed packages in your venv. You can use this list later as reference to see what packages should be installed.
```bash ```shell
pip freeze > requirements.txt pip freeze > requirements.txt
``` ```
@ -169,41 +176,38 @@ At this point we recommend creating a list of the additional packages that you n
- Community AA apps (e.g. aa-structures) - Community AA apps (e.g. aa-structures)
- Additional tools you are using (e.g. flower, django-extensions) - Additional tools you are using (e.g. flower, django-extensions)
```eval_rst :::{hint}
.. hint::
While `requirements.txt` will contain a complete list of your packages, it will also contain many packages that are automatically installed as dependencies and don't need be manually reinstalled. While `requirements.txt` will contain a complete list of your packages, it will also contain many packages that are automatically installed as dependencies and don't need be manually reinstalled.
``` :::
:::{note}
```eval_rst
.. note::
Some guide on the Internet will suggest to use use the requirements.txt file to recreate a venv. This is indeed possible, but only works if all packages can be installed from PyPI. Since most community apps are installed directly from repos this guide will not follow that approach. Some guide on the Internet will suggest to use use the requirements.txt file to recreate a venv. This is indeed possible, but only works if all packages can be installed from PyPI. Since most community apps are installed directly from repos this guide will not follow that approach.
``` :::
Leave the venv and shutdown all AA services: Leave the venv and shutdown all AA services:
```bash ```shell
deactivate deactivate
``` ```
```bash ```shell
supervisorctl stop myauth: supervisorctl stop myauth:
``` ```
Rename and keep your old venv so we have a fallback in case of some unforeseeable issues: Rename and keep your old venv so we have a fallback in case of some unforeseeable issues:
```bash ```shell
mv /home/allianceserver/venv/auth /home/allianceserver/venv/auth_old mv /home/allianceserver/venv/auth /home/allianceserver/venv/auth_old
``` ```
## Create your new venv ## Create your new venv
Now let's create our new venv with Python 3.10 and activate it: Now let's create our new venv with Python 3.11 and activate it:
```bash ```shell
python3.10 -m venv /home/allianceserver/venv/auth python3.11 -m venv /home/allianceserver/venv/auth
``` ```
```bash ```shell
source /home/allianceserver/venv/auth/bin/activate source /home/allianceserver/venv/auth/bin/activate
``` ```
@ -213,17 +217,17 @@ Now we need to reinstall all packages into your new venv.
### Install basic packages ### Install basic packages
```bash ```shell
pip install -U pip setuptools wheel pip install -U pip setuptools wheel
``` ```
### Installing AA & Gunicorn ### Installing AA & Gunicorn
```bash ```shell
pip install allianceauth pip install allianceauth
``` ```
```bash ```shell
pip install gunicorn pip install gunicorn
``` ```
@ -235,13 +239,13 @@ Use the list of packages you created earlier as a checklist. Alternatively you u
To check whether you are missing any apps you can also run the check command: To check whether you are missing any apps you can also run the check command:
```bash ```shell
python manage.py check python manage.py check
``` ```
Note: In case you forget to install an app you will get this error Note: In case you forget to install an app you will get this error
```bash ```shell
ModuleNotFoundError: No module named 'xyz' ModuleNotFoundError: No module named 'xyz'
``` ```
@ -251,7 +255,7 @@ Note that you should not need to run any migrations unless you forgot to upgrade
After you have completed installing all packages just start your AA supervisor again. After you have completed installing all packages just start your AA supervisor again.
```bash ```shell
supervisorctl start myauth: supervisorctl start myauth:
``` ```
@ -263,7 +267,7 @@ In case you run into any major issue you can always switch back to your initial
Before you start double-check that you still have your old venv for auth: Before you start double-check that you still have your old venv for auth:
```bash ```shell
ls /home/allianceserver/venv/auth /home/allianceserver/venv ls /home/allianceserver/venv/auth /home/allianceserver/venv
``` ```
@ -274,18 +278,18 @@ If the output shows these two folders you should be safe to proceed:
Run these commands to remove your current venv and switch back to the old venv for auth: Run these commands to remove your current venv and switch back to the old venv for auth:
```bash ```shell
supervisorctl stop myauth: supervisorctl stop myauth:
``` ```
```bash ```shell
rm -rf /home/allianceserver/venv/auth rm -rf /home/allianceserver/venv/auth
``` ```
```bash ```shell
mv /home/allianceserver/venv/auth_old /home/allianceserver/venv/auth mv /home/allianceserver/venv/auth_old /home/allianceserver/venv/auth
``` ```
```bash ```shell
supervisorctl start myauth: supervisorctl start myauth:
``` ```

View File

@ -13,11 +13,9 @@ Your auth project is just a regular Django project - you can add in [other Djang
The following instructions will explain how you can remove an app properly fom your Alliance Auth installation. The following instructions will explain how you can remove an app properly fom your Alliance Auth installation.
```eval_rst :::{note}
.. note::
We recommend following these instructions to avoid dangling foreign keys or orphaned Python packages on your system, which might cause conflicts with other apps down the road. We recommend following these instructions to avoid dangling foreign keys or orphaned Python packages on your system, which might cause conflicts with other apps down the road.
:::
```
### Step 1 - Removing database tables ### Step 1 - Removing database tables
@ -27,7 +25,7 @@ First, we want to remove the app related tables from the database.
Let's first try the automatic approach by running the following command: Let's first try the automatic approach by running the following command:
```sh ```shell
python manage.py migrate appname zero python manage.py migrate appname zero
``` ```
@ -39,32 +37,32 @@ If that did not work and you got error messages, you will need to remove the tab
First, tell Django that these migrations are no longer in effect (note the additional `--fake`): First, tell Django that these migrations are no longer in effect (note the additional `--fake`):
```sh ```shell
python manage.py migrate appname zero --fake python manage.py migrate appname zero --fake
``` ```
Then, open the mysql tool and connect to your Alliance Auth database: Then, open the mysql tool and connect to your Alliance Auth database:
```sh ```shell
sudo mysql -u root sudo mysql -u root
use alliance_auth; use alliance_auth;
``` ```
Next disable foreign key check. This makes it much easier to drop tables in any order. Next disable foreign key check. This makes it much easier to drop tables in any order.
```sh ```shell
SET FOREIGN_KEY_CHECKS=0; SET FOREIGN_KEY_CHECKS=0;
``` ```
Then get a list of all tables. All tables belonging to the app in question will start with `appname_`. Then get a list of all tables. All tables belonging to the app in question will start with `appname_`.
```sh ```shell
show tables; show tables;
``` ```
Now, drop the tables from the app one by one like so: Now, drop the tables from the app one by one like so:
```sh ```shell
drop table appname_model_1; drop table appname_model_1;
drop table appname_model_2; drop table appname_model_2;
... ...
@ -72,7 +70,7 @@ drop table appname_model_2;
And finally, but very importantly, re-enable foreign key checks again and then exit: And finally, but very importantly, re-enable foreign key checks again and then exit:
```sh ```shell
SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS=1;
exit; exit;
``` ```
@ -85,7 +83,7 @@ Once the tables have been removed, you you can remove the app from Alliance Auth
Finally, we want to remove the app's Python package. For that run the following command: Finally, we want to remove the app's Python package. For that run the following command:
```sh ```shell
pip uninstall app-package-name pip uninstall app-package-name
``` ```

View File

@ -2,12 +2,11 @@
In the maintenance chapter you find details about where important log files are found, how you can customize your AA installation and how to solve common issues. In the maintenance chapter you find details about where important log files are found, how you can customize your AA installation and how to solve common issues.
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
apps apps
project project
troubleshooting troubleshooting
tuning/index tuning/index
``` :::

View File

@ -24,7 +24,7 @@ Make sure the background processes are running: `supervisorctl status myauth:`.
Stop celery workers with `supervisorctl stop myauth:worker` then clear the queue: Stop celery workers with `supervisorctl stop myauth:worker` then clear the queue:
```bash ```shell
redis-cli FLUSHALL redis-cli FLUSHALL
celery -A myauth worker --purge celery -A myauth worker --purge
``` ```
@ -49,7 +49,7 @@ Gunicorn needs to have context for its running location, `/home/alllianceserver/
Migrations may about with the following error message: Migrations may about with the following error message:
```bash ```shell
Specified key was too long; max key length is 767 bytes Specified key was too long; max key length is 767 bytes
``` ```

View File

@ -1,26 +1,26 @@
# Celery # Celery
```eval_rst :::{hint}
.. hint::
Most tunings will require a change to your supervisor configuration in your `supervisor.conf` file. Note that you need to restart the supervisor daemon in order for any changes to take effect. And before restarting the daemon you may want to make sure your supervisors stop gracefully:(Ubuntu): Most tunings will require a change to your supervisor configuration in your `supervisor.conf` file. Note that you need to restart the supervisor daemon in order for any changes to take effect. And before restarting the daemon you may want to make sure your supervisors stop gracefully:(Ubuntu):
:: ```bash
supervisor stop myauth: supervisor stop myauth:
systemctl supervisor restart systemctl supervisor restart
``` ```
:::
## Task Logging ## Task Logging
By default task logging is deactivated. Enabling task logging allows you to monitor what tasks are doing in addition to getting all warnings and error messages. To enable info logging for tasks add the following to the command configuration of your worker in the `supervisor.conf` file: By default task logging is deactivated. Enabling task logging allows you to monitor what tasks are doing in addition to getting all warnings and error messages. To enable info logging for tasks add the following to the command configuration of your worker in the `supervisor.conf` file:
```text ```ini
-l info -l info
``` ```
Full example: Full example:
```text ```ini
command=/home/allianceserver/venv/auth/bin/celery -A myauth worker -l info command=/home/allianceserver/venv/auth/bin/celery -A myauth worker -l info
``` ```
@ -28,11 +28,9 @@ command=/home/allianceserver/venv/auth/bin/celery -A myauth worker -l info
Celery workers often have memory leaks and will therefore grow in size over time. While the Alliance Auth team is working hard to ensure Auth is free of memory leaks some may still be cause by bugs in different versions of libraries or community apps. It is therefore good practice to enable features that protect against potential memory leaks. Celery workers often have memory leaks and will therefore grow in size over time. While the Alliance Auth team is working hard to ensure Auth is free of memory leaks some may still be cause by bugs in different versions of libraries or community apps. It is therefore good practice to enable features that protect against potential memory leaks.
```eval_rst :::{hint}
.. hint::
The 256 MB limit is just an example and should be adjusted to your system configuration. We would suggest to not go below 128MB though, since new workers start with around 80 MB already. Also take into consideration that this value is per worker and that you may have more than one worker running in your system. The 256 MB limit is just an example and should be adjusted to your system configuration. We would suggest to not go below 128MB though, since new workers start with around 80 MB already. Also take into consideration that this value is per worker and that you may have more than one worker running in your system.
``` :::
### Supervisor ### Supervisor
@ -42,13 +40,13 @@ This is not a built in feature and requires the 3rd party extension [superlance]
To setup install superlance into your venv with: To setup install superlance into your venv with:
```bash ```shell
pip install superlance pip install superlance
``` ```
You can then add `memmon` to your `supervisor.conf`: You can then add `memmon` to your `supervisor.conf`:
```text ```ini
[eventlistener:memmon] [eventlistener:memmon]
command=/home/allianceserver/venv/auth/bin/memmon -p worker=256MB command=/home/allianceserver/venv/auth/bin/memmon -p worker=256MB
directory=/home/allianceserver/myauth directory=/home/allianceserver/myauth
@ -67,7 +65,7 @@ Celery tasks are designed to run concurrently, so one obvious way to increase ta
The easiest way to increate throughput can be achieved by increasing the `numprocs` parameter of the suprvisor process. For example: The easiest way to increate throughput can be achieved by increasing the `numprocs` parameter of the suprvisor process. For example:
```text ```ini
[program:worker] [program:worker]
... ...
numprocs=2 numprocs=2
@ -77,48 +75,45 @@ process_name=%(program_name)s_%(process_num)02d
This number will be multiplied by your concurrency setting, This number will be multiplied by your concurrency setting,
``` ```text
numprocs * concurency = workers numprocs * concurency = workers
``` ```
increasing this number will require a modification to the memmon settings as each `numproc` worker will get a unique name for example with `numproc=3` increasing this number will require a modification to the memmon settings as each `numproc` worker will get a unique name for example with `numproc=3`
```text ```ini
[eventlistener:memmon] [eventlistener:memmon]
... ...
command=... -p worker_00=256MB -p worker_01=256MB -p worker_02=256MB command=... -p worker_00=256MB -p worker_01=256MB -p worker_02=256MB
... ...
``` ```
```eval_rst :::{hint}
.. hint::
You will want to experiment with different settings to find the optimal. One way to generate task load and verify your configuration is to run a model update with the following command: You will want to experiment with different settings to find the optimal. One way to generate task load and verify your configuration is to run a model update with the following command:
:: ```bash
celery -A myauth call allianceauth.eveonline.tasks.run_model_update celery -A myauth call allianceauth.eveonline.tasks.run_model_update
``` ```
:::
### Concurrency ### Concurrency
This can be achieved by the setting the concurrency parameter of the celery worker to a higher number. For example: This can be achieved by the setting the concurrency parameter of the celery worker to a higher number. For example:
```text ```ini
--concurrency=10 --concurrency=10
``` ```
```eval_rst :::{hint}
.. hint::
The optimal number will hugely depend on your individual system configuration and you may want to experiment with different settings to find the optimal. One way to generate task load and verify your configuration is to run a model update with the following command: The optimal number will hugely depend on your individual system configuration and you may want to experiment with different settings to find the optimal. One way to generate task load and verify your configuration is to run a model update with the following command:
:: ```bash
celery -A myauth call allianceauth.eveonline.tasks.run_model_update celery -A myauth call allianceauth.eveonline.tasks.run_model_update
``` ```
```eval_rst :::
.. hint::
:::{hint}
The optimal number of concurrent workers will be different for every system and we recommend experimenting with different figures to find the optimal for your system. Note, that the example of 10 threads is conservative and should work even with smaller systems. The optimal number of concurrent workers will be different for every system and we recommend experimenting with different figures to find the optimal for your system. Note, that the example of 10 threads is conservative and should work even with smaller systems.
``` :::

View File

@ -8,6 +8,6 @@ The number you set this to will depend on your own server environment, how many
For example to get 5 workers change the setting `--workers=5` in your `supervisor.conf` file and then reload the supervisor with the following command to activate the change (Ubuntu): For example to get 5 workers change the setting `--workers=5` in your `supervisor.conf` file and then reload the supervisor with the following command to activate the change (Ubuntu):
```bash ```shell
systemctl restart supervisor systemctl restart supervisor
``` ```

View File

@ -2,16 +2,16 @@
The official installation guide will install a stable version of Alliance Auth that will work fine for most cases. However, there are a lot of levels that can be used to optimize a system. For example some installations may we short on RAM and want to reduce the total memory footprint, even though that may reduce system performance. Others are fine with further increasing the memory footprint to get better system performance. The official installation guide will install a stable version of Alliance Auth that will work fine for most cases. However, there are a lot of levels that can be used to optimize a system. For example some installations may we short on RAM and want to reduce the total memory footprint, even though that may reduce system performance. Others are fine with further increasing the memory footprint to get better system performance.
```eval_rst :::{warning}
.. warning::
Tuning usually has benefits and costs and should only be performed by experienced Linux administrators who understand the impact of tuning decisions on to their system. Tuning usually has benefits and costs and should only be performed by experienced Linux administrators who understand the impact of tuning decisions on to their system.
``` :::
```eval_rst :::{toctree}
.. toctree::
:maxdepth: 1 :maxdepth: 1
gunicorn gunicorn
celery celery
redis redis
python
sql
``` ```

View File

@ -0,0 +1,633 @@
# Python
## Version Update
Newer versions of python can focus heavily on performance improvements, some more than others. But be aware regressions for stability or security reasons may always be the case.
As a general rule, Python 3.9 and Python 3.11 both had a strong focus on performance improvements. Python 3.12 is looking promising but has yet to have widespread testing, adoption and deployment. A simple comparison is available at [speed.python.org](https://speed.python.org/comparison/?exe=12%2BL%2B3.11%2C12%2BL%2B3.12%2C12%2BL%2B3.10%2C12%2BL%2B3.9%2C12%2BL%2B3.8&ben=746&env=1&hor=false&bas=none&chart=normal+bars).
[Djangobench](https://github.com/django/djangobench/tree/master) is source of synthetic benchmarks and a useful tool for running comparisons. Below are some examples to inform your investigations.
Keep in mind while a 1.2x faster result is significant, it's only one step of the process, Celery, SQL, Redis and many other factors will influence the end result and this _python_ speed improvement will not translate 1:1 into real world performance.
### Django 4.0.10
- Djangobench 0.10.0
- Django 4.0.10
- Python 3.8.18 vs Python 3.11.5
```bash
joel@METABOX:~/djangobench/django$ djangobench --vcs=none --control=. --experiment=. --control-python=/home/joel/djangobench/py38/bin/python --experiment-python=/home/joel/djangobench/py311/bin/python -r /home/joel/djangobench/results -t 500
Running all benchmarks
Recording data to '/home/joel/djangobench/results'
Control: Django 4.0.10 (in .)
Experiment: Django 4.0.10 (in .)
Running 'multi_value_dict' benchmark ...
Min: 0.000014 -> 0.000013: 1.0304x faster
Avg: 0.000183 -> 0.000133: 1.3698x faster
Significant (t=9.325958)
Stddev: 0.00010 -> 0.00007: 1.3791x smaller (N = 500)
Running 'query_values' benchmark ...
Min: 0.000079 -> 0.000070: 1.1308x faster
Avg: 0.000084 -> 0.000074: 1.1267x faster
Significant (t=19.174361)
Stddev: 0.00001 -> 0.00001: 1.0255x larger (N = 500)
Running 'query_delete' benchmark ...
Min: 0.000082 -> 0.000074: 1.1145x faster
Avg: 0.000086 -> 0.000078: 1.0987x faster
Significant (t=17.504085)
Stddev: 0.00001 -> 0.00001: 1.1888x smaller (N = 500)
Running 'query_select_related' benchmark ...
Min: 0.016771 -> 0.013520: 1.2405x faster
Avg: 0.017897 -> 0.014149: 1.2649x faster
Significant (t=40.942990)
Stddev: 0.00190 -> 0.00077: 2.4535x smaller (N = 500)
Running 'query_aggregate' benchmark ...
Min: 0.000092 -> 0.000083: 1.1105x faster
Avg: 0.000100 -> 0.000090: 1.1107x faster
Significant (t=9.967204)
Stddev: 0.00002 -> 0.00001: 1.5003x smaller (N = 500)
Running 'query_raw_deferred' benchmark ...
Min: 0.004157 -> 0.003563: 1.1666x faster
Avg: 0.004626 -> 0.003809: 1.2143x faster
Significant (t=12.325104)
Stddev: 0.00121 -> 0.00086: 1.4047x smaller (N = 500)
Running 'query_get_or_create' benchmark ...
Min: 0.000412 -> 0.000362: 1.1385x faster
Avg: 0.000458 -> 0.000407: 1.1259x faster
Significant (t=14.169322)
Stddev: 0.00006 -> 0.00005: 1.1306x smaller (N = 500)
Running 'query_values_list' benchmark ...
Min: 0.000080 -> 0.000071: 1.1231x faster
Avg: 0.000089 -> 0.000076: 1.1706x faster
Significant (t=18.298942)
Stddev: 0.00001 -> 0.00001: 1.9398x smaller (N = 500)
Running 'url_resolve_flat_i18n_off' benchmark ...
Min: 0.055764 -> 0.045370: 1.2291x faster
Avg: 0.057670 -> 0.047020: 1.2265x faster
Significant (t=111.187780)
Stddev: 0.00206 -> 0.00059: 3.4618x smaller (N = 500)
Running 'qs_filter_chaining' benchmark ...
Min: 0.000236 -> 0.000196: 1.2034x faster
Avg: 0.000248 -> 0.000206: 1.2041x faster
Significant (t=44.893544)
Stddev: 0.00002 -> 0.00001: 1.0833x smaller (N = 500)
Running 'template_render' benchmark ...
Min: 0.000933 -> 0.000712: 1.3110x faster
Avg: 0.001003 -> 0.000777: 1.2909x faster
Significant (t=8.379095)
Stddev: 0.00043 -> 0.00042: 1.0287x smaller (N = 500)
Running 'query_get' benchmark ...
Min: 0.000259 -> 0.000230: 1.1259x faster
Avg: 0.000282 -> 0.000238: 1.1829x faster
Significant (t=42.267305)
Stddev: 0.00002 -> 0.00001: 1.7842x smaller (N = 500)
Running 'query_none' benchmark ...
Min: 0.000053 -> 0.000045: 1.1830x faster
Avg: 0.000056 -> 0.000049: 1.1449x faster
Significant (t=16.426843)
Stddev: 0.00001 -> 0.00001: 1.1267x larger (N = 500)
Running 'query_complex_filter' benchmark ...
Min: 0.000039 -> 0.000034: 1.1527x faster
Avg: 0.000041 -> 0.000037: 1.1091x faster
Significant (t=13.582718)
Stddev: 0.00000 -> 0.00001: 1.5373x larger (N = 500)
Running 'query_filter' benchmark ...
Min: 0.000127 -> 0.000112: 1.1288x faster
Avg: 0.000133 -> 0.000119: 1.1228x faster
Significant (t=22.727829)
Stddev: 0.00001 -> 0.00001: 1.1771x smaller (N = 500)
Running 'template_render_simple' benchmark ...
Min: 0.000030 -> 0.000024: 1.2405x faster
Avg: 0.000035 -> 0.000029: 1.2042x faster
Not significant
Stddev: 0.00007 -> 0.00005: 1.3190x smaller (N = 500)
Running 'default_middleware' benchmark ...
Min: -0.000047 -> -0.000054: 0.8624x faster
Avg: 0.000017 -> 0.000017: 1.0032x faster
Not significant
Stddev: 0.00037 -> 0.00037: 1.0091x larger (N = 500)
Running 'query_annotate' benchmark ...
Min: 0.000186 -> 0.000162: 1.1505x faster
Avg: 0.000207 -> 0.000178: 1.1660x faster
Significant (t=16.516089)
Stddev: 0.00003 -> 0.00003: 1.1403x smaller (N = 500)
Running 'raw_sql' benchmark ...
Min: 0.000015 -> 0.000013: 1.1070x faster
Avg: 0.000017 -> 0.000014: 1.1676x faster
Significant (t=13.598519)
Stddev: 0.00000 -> 0.00000: 2.3503x smaller (N = 500)
Running 'url_resolve_flat' benchmark ...
Min: 0.056378 -> 0.044772: 1.2592x faster
Avg: 0.058268 -> 0.046656: 1.2489x faster
Significant (t=197.176590)
Stddev: 0.00121 -> 0.00051: 2.3665x smaller (N = 500)
Running 'l10n_render' benchmark ...
Min: 0.001097 -> 0.000727: 1.5092x faster
Avg: 0.001160 -> 0.000768: 1.5101x faster
Significant (t=36.971179)
Stddev: 0.00019 -> 0.00014: 1.2946x smaller (N = 500)
Running 'query_count' benchmark ...
Min: 0.000083 -> 0.000073: 1.1302x faster
Avg: 0.000091 -> 0.000079: 1.1640x faster
Significant (t=15.049336)
Stddev: 0.00002 -> 0.00001: 1.6661x smaller (N = 500)
Running 'model_delete' benchmark ...
Min: 0.000123 -> 0.000105: 1.1701x faster
Avg: 0.000135 -> 0.000119: 1.1396x faster
Significant (t=17.781816)
Stddev: 0.00001 -> 0.00002: 1.1990x larger (N = 500)
Running 'query_iterator' benchmark ...
Min: 0.000102 -> 0.000088: 1.1605x faster
Avg: 0.000108 -> 0.000093: 1.1598x faster
Significant (t=23.872009)
Stddev: 0.00001 -> 0.00001: 1.1366x smaller (N = 500)
Running 'template_compilation' benchmark ...
Min: 0.000155 -> 0.000129: 1.2015x faster
Avg: 0.000169 -> 0.000137: 1.2317x faster
Significant (t=6.119618)
Stddev: 0.00009 -> 0.00007: 1.4162x smaller (N = 500)
Running 'query_all_multifield' benchmark ...
Min: 0.014582 -> 0.012509: 1.1658x faster
Avg: 0.015715 -> 0.013337: 1.1783x faster
Significant (t=19.183517)
Stddev: 0.00207 -> 0.00184: 1.1241x smaller (N = 500)
Running 'query_prefetch_related' benchmark ...
Min: 0.014293 -> 0.012157: 1.1758x faster
Avg: 0.015467 -> 0.013276: 1.1650x faster
Significant (t=20.607411)
Stddev: 0.00176 -> 0.00160: 1.0952x smaller (N = 500)
Running 'query_all_converters' benchmark ...
Min: 0.000536 -> 0.000464: 1.1554x faster
Avg: 0.000563 -> 0.000486: 1.1595x faster
Significant (t=38.503433)
Stddev: 0.00004 -> 0.00002: 1.6468x smaller (N = 500)
Running 'query_distinct' benchmark ...
Min: 0.000106 -> 0.000092: 1.1583x faster
Avg: 0.000127 -> 0.000096: 1.3223x faster
Significant (t=27.798102)
Stddev: 0.00002 -> 0.00001: 3.7187x smaller (N = 500)
Running 'query_dates' benchmark ...
Min: 0.000249 -> 0.000209: 1.1953x faster
Avg: 0.000275 -> 0.000228: 1.2056x faster
Significant (t=30.785168)
Stddev: 0.00003 -> 0.00002: 1.0854x smaller (N = 500)
Running 'model_save_existing' benchmark ...
Min: 0.003526 -> 0.003094: 1.1397x faster
Avg: 0.003723 -> 0.003212: 1.1591x faster
Significant (t=47.274918)
Stddev: 0.00018 -> 0.00016: 1.1817x smaller (N = 500)
Running 'query_delete_related' benchmark ...
Min: 0.000120 -> 0.000103: 1.1655x faster
Avg: 0.000132 -> 0.000111: 1.1815x faster
Significant (t=6.428771)
Stddev: 0.00005 -> 0.00004: 1.2149x smaller (N = 500)
Running 'url_reverse' benchmark ...
Min: 0.000062 -> 0.000060: 1.0318x faster
Avg: 0.000072 -> 0.000068: 1.0622x faster
Not significant
Stddev: 0.00006 -> 0.00005: 1.0531x smaller (N = 500)
Running 'query_latest' benchmark ...
Min: 0.000136 -> 0.000118: 1.1454x faster
Avg: 0.000155 -> 0.000129: 1.2008x faster
Significant (t=8.372115)
Stddev: 0.00007 -> 0.00001: 5.1365x smaller (N = 500)
Running 'form_create' benchmark ...
Min: 0.000015 -> 0.000013: 1.2319x faster
Avg: 0.000019 -> 0.000015: 1.2739x faster
Significant (t=4.158080)
Stddev: 0.00002 -> 0.00001: 1.1449x smaller (N = 500)
Running 'query_update' benchmark ...
Min: 0.000047 -> 0.000041: 1.1323x faster
Avg: 0.000052 -> 0.000044: 1.1721x faster
Significant (t=18.470635)
Stddev: 0.00001 -> 0.00000: 1.6104x smaller (N = 500)
Running 'query_in_bulk' benchmark ...
Min: 0.000152 -> 0.000136: 1.1193x faster
Avg: 0.000173 -> 0.000147: 1.1735x faster
Significant (t=16.901845)
Stddev: 0.00003 -> 0.00001: 2.1199x smaller (N = 500)
Running 'url_resolve_nested' benchmark ...
Min: 0.000043 -> 0.000034: 1.2871x faster
Avg: 0.000075 -> 0.000047: 1.6049x faster
Not significant
Stddev: 0.00066 -> 0.00023: 2.8387x smaller (N = 500)
Running 'model_creation' benchmark ...
Min: 0.000077 -> 0.000066: 1.1579x faster
Avg: 0.000088 -> 0.000072: 1.2205x faster
Significant (t=10.514202)
Stddev: 0.00003 -> 0.00001: 3.1410x smaller (N = 500)
Running 'query_order_by' benchmark ...
Min: 0.000135 -> 0.000124: 1.0945x faster
Avg: 0.000145 -> 0.000133: 1.0902x faster
Significant (t=13.574502)
Stddev: 0.00001 -> 0.00001: 1.1586x smaller (N = 500)
Running 'startup' benchmark ...
Skipped: Django 1.9 and later has changed app loading. This benchmark needs fixing anyway.
Running 'form_clean' benchmark ...
Min: 0.000005 -> 0.000003: 1.4696x faster
Avg: 0.000006 -> 0.000004: 1.4931x faster
Significant (t=11.263253)
Stddev: 0.00000 -> 0.00000: 2.2571x smaller (N = 500)
Running 'locale_from_request' benchmark ...
Min: 0.000076 -> 0.000082: 1.0895x slower
Avg: 0.000083 -> 0.000090: 1.0877x slower
Not significant
Stddev: 0.00009 -> 0.00006: 1.6230x smaller (N = 500)
Running 'query_exists' benchmark ...
Min: 0.000243 -> 0.000214: 1.1399x faster
Avg: 0.000262 -> 0.000227: 1.1571x faster
Significant (t=27.797738)
Stddev: 0.00002 -> 0.00002: 1.2601x smaller (N = 500)
Running 'query_values_10000' benchmark ...
Min: 0.005755 -> 0.005269: 1.0923x faster
Avg: 0.006184 -> 0.005587: 1.1067x faster
Significant (t=10.895954)
Stddev: 0.00094 -> 0.00079: 1.1902x smaller (N = 500)
Running 'query_exclude' benchmark ...
Min: 0.000159 -> 0.000141: 1.1256x faster
Avg: 0.000177 -> 0.000151: 1.1741x faster
Significant (t=23.556200)
Stddev: 0.00002 -> 0.00001: 1.8250x smaller (N = 500)
Running 'query_raw' benchmark ...
Min: 0.005619 -> 0.004860: 1.1562x faster
Avg: 0.006181 -> 0.005041: 1.2263x faster
Significant (t=18.008590)
Stddev: 0.00121 -> 0.00074: 1.6376x smaller (N = 500)
Running 'url_resolve' benchmark ...
Min: 0.004666 -> 0.004233: 1.1023x faster
Avg: 0.004920 -> 0.004347: 1.1318x faster
Significant (t=24.865249)
Stddev: 0.00049 -> 0.00016: 3.1507x smaller (N = 500)
Running 'model_save_new' benchmark ...
Min: 0.003420 -> 0.003105: 1.1014x faster
Avg: 0.003610 -> 0.003217: 1.1221x faster
Significant (t=42.956103)
Stddev: 0.00017 -> 0.00011: 1.6304x smaller (N = 500)
Running 'query_all' benchmark ...
Min: 0.008101 -> 0.007077: 1.1447x faster
Avg: 0.009006 -> 0.007936: 1.1348x faster
Significant (t=9.981534)
Stddev: 0.00171 -> 0.00168: 1.0215x smaller (N = 500)
```
### Django 4.2.6
- Djangobench 0.10.0
- Django 4.0.10
- Python 3.8.18 vs Python 3.11.5
```bash
joel@METABOX:~/djangobench/django$ djangobench --vcs=none --control=. --experiment=. --control-python=/home/joel/djangobench/py38/bin/python --experiment-python=/home/joel/djangobench/py311/bin/python -r /home/joel/djangobench/results -t 500
Running all benchmarks
Recording data to '/home/joel/djangobench/results'
Control: Django 4.2.6 (in .)
Experiment: Django 4.2.6 (in .)
Running 'multi_value_dict' benchmark ...
Min: -0.000004 -> 0.000013: -3.0336x slower
Avg: 0.000182 -> 0.000133: 1.3680x faster
Significant (t=9.151616)
Stddev: 0.00010 -> 0.00007: 1.3826x smaller (N = 500)
Running 'query_values' benchmark ...
Min: 0.000082 -> 0.000072: 1.1485x faster
Avg: 0.000086 -> 0.000075: 1.1462x faster
Significant (t=30.114973)
Stddev: 0.00001 -> 0.00001: 1.0258x larger (N = 500)
Running 'query_delete' benchmark ...
Min: 0.000080 -> 0.000071: 1.1169x faster
Avg: 0.000086 -> 0.000077: 1.1088x faster
Significant (t=13.459411)
Stddev: 0.00001 -> 0.00001: 1.0008x smaller (N = 500)
Running 'query_select_related' benchmark ...
Min: 0.016889 -> 0.013513: 1.2498x faster
Avg: 0.018370 -> 0.013885: 1.3230x faster
Significant (t=48.921967)
Stddev: 0.00196 -> 0.00061: 3.2174x smaller (N = 500)
Running 'query_aggregate' benchmark ...
Min: 0.000167 -> 0.000153: 1.0904x faster
Avg: 0.000182 -> 0.000165: 1.1029x faster
Significant (t=12.685517)
Stddev: 0.00002 -> 0.00002: 1.3019x smaller (N = 500)
Running 'query_raw_deferred' benchmark ...
Min: 0.004160 -> 0.003674: 1.1323x faster
Avg: 0.004596 -> 0.003888: 1.1820x faster
Significant (t=11.504156)
Stddev: 0.00117 -> 0.00073: 1.5957x smaller (N = 500)
Running 'query_get_or_create' benchmark ...
Min: 0.000421 -> 0.000356: 1.1823x faster
Avg: 0.000470 -> 0.000392: 1.2011x faster
Significant (t=14.613017)
Stddev: 0.00008 -> 0.00009: 1.0954x larger (N = 500)
Running 'query_values_list' benchmark ...
Min: 0.000080 -> 0.000070: 1.1395x faster
Avg: 0.000085 -> 0.000075: 1.1202x faster
Significant (t=20.300988)
Stddev: 0.00001 -> 0.00001: 1.0537x smaller (N = 500)
Running 'url_resolve_flat_i18n_off' benchmark ...
Min: 0.056031 -> 0.045854: 1.2219x faster
Avg: 0.057048 -> 0.048370: 1.1794x faster
Significant (t=106.668460)
Stddev: 0.00117 -> 0.00139: 1.1819x larger (N = 500)
Running 'qs_filter_chaining' benchmark ...
Min: 0.000247 -> 0.000205: 1.2080x faster
Avg: 0.000267 -> 0.000219: 1.2211x faster
Significant (t=38.507950)
Stddev: 0.00002 -> 0.00002: 1.0252x larger (N = 500)
Running 'template_render' benchmark ...
Min: 0.000956 -> 0.000761: 1.2550x faster
Avg: 0.001061 -> 0.000862: 1.2302x faster
Significant (t=6.128572)
Stddev: 0.00052 -> 0.00051: 1.0109x smaller (N = 500)
Running 'query_get' benchmark ...
Min: 0.000268 -> 0.000235: 1.1388x faster
Avg: 0.000293 -> 0.000256: 1.1411x faster
Significant (t=24.002331)
Stddev: 0.00002 -> 0.00003: 1.2917x larger (N = 500)
Running 'query_none' benchmark ...
Min: 0.000055 -> 0.000050: 1.1079x faster
Avg: 0.000061 -> 0.000055: 1.1183x faster
Significant (t=3.149707)
Stddev: 0.00003 -> 0.00004: 1.3162x larger (N = 500)
Running 'query_complex_filter' benchmark ...
Min: 0.000040 -> 0.000034: 1.1777x faster
Avg: 0.000042 -> 0.000038: 1.1267x faster
Significant (t=15.246074)
Stddev: 0.00000 -> 0.00001: 1.5250x larger (N = 500)
Running 'query_filter' benchmark ...
Min: 0.000131 -> 0.000116: 1.1288x faster
Avg: 0.000139 -> 0.000127: 1.0907x faster
Significant (t=14.448319)
Stddev: 0.00001 -> 0.00001: 1.2281x larger (N = 500)
Running 'template_render_simple' benchmark ...
Min: 0.000031 -> 0.000024: 1.2650x faster
Avg: 0.000037 -> 0.000029: 1.2895x faster
Significant (t=2.094800)
Stddev: 0.00007 -> 0.00005: 1.3630x smaller (N = 500)
Running 'default_middleware' benchmark ...
Min: -0.000037 -> -0.000060: 0.6180x faster
Avg: 0.000001 -> 0.000001: 1.0056x slower
Not significant
Stddev: 0.00002 -> 0.00002: 1.0915x smaller (N = 500)
Running 'query_annotate' benchmark ...
Min: 0.000192 -> 0.000173: 1.1122x faster
Avg: 0.000206 -> 0.000185: 1.1134x faster
Significant (t=17.849733)
Stddev: 0.00002 -> 0.00002: 1.0456x smaller (N = 500)
Running 'raw_sql' benchmark ...
Min: 0.000013 -> 0.000012: 1.0839x faster
Avg: 0.000015 -> 0.000014: 1.0882x faster
Significant (t=4.252084)
Stddev: 0.00001 -> 0.00000: 1.5868x smaller (N = 500)
Running 'url_resolve_flat' benchmark ...
Min: 0.055540 -> 0.046018: 1.2069x faster
Avg: 0.058030 -> 0.048408: 1.1988x faster
Significant (t=98.852976)
Stddev: 0.00157 -> 0.00151: 1.0444x smaller (N = 500)
Running 'l10n_render' benchmark ...
Min: 0.001604 -> 0.001253: 1.2797x faster
Avg: 0.001684 -> 0.001304: 1.2918x faster
Significant (t=37.535402)
Stddev: 0.00017 -> 0.00015: 1.1476x smaller (N = 500)
Running 'query_count' benchmark ...
Min: 0.000176 -> 0.000165: 1.0631x faster
Avg: 0.000189 -> 0.000176: 1.0755x faster
Significant (t=12.229046)
Stddev: 0.00002 -> 0.00002: 1.0395x larger (N = 500)
Running 'model_delete' benchmark ...
Min: 0.000122 -> 0.000104: 1.1743x faster
Avg: 0.000152 -> 0.000115: 1.3227x faster
Significant (t=19.812953)
Stddev: 0.00004 -> 0.00001: 2.6554x smaller (N = 500)
Running 'query_iterator' benchmark ...
Min: 0.000108 -> 0.000094: 1.1518x faster
Avg: 0.000119 -> 0.000098: 1.2203x faster
Significant (t=21.984884)
Stddev: 0.00002 -> 0.00001: 2.7750x smaller (N = 500)
Running 'template_compilation' benchmark ...
Min: 0.000164 -> 0.000148: 1.1034x faster
Avg: 0.000184 -> 0.000162: 1.1386x faster
Significant (t=4.665298)
Stddev: 0.00008 -> 0.00007: 1.2952x smaller (N = 500)
Running 'query_all_multifield' benchmark ...
Min: 0.014802 -> 0.012188: 1.2144x faster
Avg: 0.016029 -> 0.013294: 1.2057x faster
Significant (t=21.516971)
Stddev: 0.00210 -> 0.00191: 1.0984x smaller (N = 500)
Running 'query_prefetch_related' benchmark ...
Min: 0.013401 -> 0.011583: 1.1569x faster
Avg: 0.014822 -> 0.013366: 1.1090x faster
Significant (t=11.422100)
Stddev: 0.00170 -> 0.00229: 1.3410x larger (N = 500)
Running 'query_all_converters' benchmark ...
Min: 0.000499 -> 0.000429: 1.1618x faster
Avg: 0.000531 -> 0.000455: 1.1670x faster
Significant (t=42.716720)
Stddev: 0.00002 -> 0.00003: 1.5394x larger (N = 500)
Running 'query_distinct' benchmark ...
Min: 0.000108 -> 0.000095: 1.1397x faster
Avg: 0.000116 -> 0.000100: 1.1646x faster
Significant (t=25.915629)
Stddev: 0.00001 -> 0.00001: 1.1204x larger (N = 500)
Running 'query_dates' benchmark ...
Min: 0.000333 -> 0.000290: 1.1490x faster
Avg: 0.000365 -> 0.000326: 1.1207x faster
Significant (t=18.213858)
Stddev: 0.00003 -> 0.00003: 1.0118x larger (N = 500)
Running 'model_save_existing' benchmark ...
Min: 0.003455 -> 0.003081: 1.1215x faster
Avg: 0.003764 -> 0.003326: 1.1316x faster
Significant (t=32.229651)
Stddev: 0.00023 -> 0.00020: 1.1398x smaller (N = 500)
Running 'query_delete_related' benchmark ...
Min: 0.000122 -> 0.000102: 1.1946x faster
Avg: 0.000131 -> 0.000113: 1.1564x faster
Significant (t=5.027485)
Stddev: 0.00005 -> 0.00006: 1.4129x larger (N = 500)
Running 'url_reverse' benchmark ...
Min: 0.000068 -> 0.000067: 1.0193x faster
Avg: 0.000075 -> 0.000074: 1.0157x faster
Not significant
Stddev: 0.00006 -> 0.00005: 1.1543x smaller (N = 500)
Running 'query_latest' benchmark ...
Min: 0.000147 -> 0.000138: 1.0631x faster
Avg: 0.000167 -> 0.000148: 1.1277x faster
Significant (t=11.353029)
Stddev: 0.00003 -> 0.00002: 1.6091x smaller (N = 500)
Running 'form_create' benchmark ...
Min: 0.000016 -> 0.000013: 1.2659x faster
Avg: 0.000020 -> 0.000015: 1.2770x faster
Significant (t=3.482649)
Stddev: 0.00002 -> 0.00002: 1.0947x larger (N = 500)
Running 'query_update' benchmark ...
Min: 0.000047 -> 0.000043: 1.0971x faster
Avg: 0.000050 -> 0.000046: 1.0691x faster
Significant (t=9.363513)
Stddev: 0.00001 -> 0.00000: 1.2636x smaller (N = 500)
Running 'query_in_bulk' benchmark ...
Min: 0.000157 -> 0.000143: 1.0970x faster
Avg: 0.000178 -> 0.000162: 1.0981x faster
Significant (t=9.031182)
Stddev: 0.00002 -> 0.00003: 1.5173x larger (N = 500)
Running 'url_resolve_nested' benchmark ...
Min: 0.000046 -> 0.000038: 1.2179x faster
Avg: 0.000075 -> 0.000052: 1.4505x faster
Not significant
Stddev: 0.00059 -> 0.00024: 2.4300x smaller (N = 500)
Running 'model_creation' benchmark ...
Min: 0.000071 -> 0.000065: 1.1058x faster
Avg: 0.000079 -> 0.000073: 1.0876x faster
Significant (t=2.786580)
Stddev: 0.00003 -> 0.00004: 1.1518x larger (N = 500)
Running 'query_order_by' benchmark ...
Min: 0.000146 -> 0.000128: 1.1407x faster
Avg: 0.000154 -> 0.000138: 1.1206x faster
Significant (t=14.021341)
Stddev: 0.00002 -> 0.00002: 1.2540x larger (N = 500)
Running 'startup' benchmark ...
Skipped: Django 1.9 and later has changed app loading. This benchmark needs fixing anyway.
Running 'form_clean' benchmark ...
Min: 0.000005 -> 0.000004: 1.4613x faster
Avg: 0.000006 -> 0.000004: 1.3654x faster
Significant (t=12.763128)
Stddev: 0.00000 -> 0.00000: 1.1666x larger (N = 500)
Running 'locale_from_request' benchmark ...
Min: 0.000097 -> 0.000108: 1.1090x slower
Avg: 0.000108 -> 0.000120: 1.1178x slower
Significant (t=-3.057677)
Stddev: 0.00007 -> 0.00006: 1.1186x smaller (N = 500)
Running 'query_exists' benchmark ...
Min: 0.000273 -> 0.000234: 1.1698x faster
Avg: 0.000290 -> 0.000248: 1.1686x faster
Significant (t=39.518859)
Stddev: 0.00002 -> 0.00002: 1.2025x smaller (N = 500)
Running 'query_values_10000' benchmark ...
Min: 0.005601 -> 0.005298: 1.0571x faster
Avg: 0.006023 -> 0.005691: 1.0583x faster
Significant (t=6.167352)
Stddev: 0.00082 -> 0.00088: 1.0752x larger (N = 500)
Running 'query_exclude' benchmark ...
Min: 0.000159 -> 0.000140: 1.1367x faster
Avg: 0.000165 -> 0.000149: 1.1020x faster
Significant (t=19.643154)
Stddev: 0.00001 -> 0.00001: 1.2636x larger (N = 500)
Running 'query_raw' benchmark ...
Min: 0.005764 -> 0.004630: 1.2450x faster
Avg: 0.006169 -> 0.004881: 1.2638x faster
Significant (t=20.996453)
Stddev: 0.00109 -> 0.00083: 1.3105x smaller (N = 500)
Running 'url_resolve' benchmark ...
Min: 0.004928 -> 0.004597: 1.0721x faster
Avg: 0.005217 -> 0.004716: 1.1063x faster
Significant (t=46.893945)
Stddev: 0.00022 -> 0.00010: 2.2192x smaller (N = 500)
Running 'model_save_new' benchmark ...
Min: 0.003404 -> 0.003012: 1.1301x faster
Avg: 0.003494 -> 0.003105: 1.1251x faster
Significant (t=45.888484)
Stddev: 0.00014 -> 0.00013: 1.0298x smaller (N = 500)
Running 'query_all' benchmark ...
Min: 0.007971 -> 0.007085: 1.1250x faster
Avg: 0.009091 -> 0.008147: 1.1159x faster
Significant (t=7.583074)
Stddev: 0.00183 -> 0.00210: 1.1518x larger (N = 500)
```

View File

@ -2,7 +2,7 @@
## Compression ## Compression
Cache compression can help tame the memory usage of specialised installation configurations and Community Apps that heavily utilize Redis. Cache compression can help tame the memory usage of specialised installation configurations and Community Apps that heavily utilize Redis, in exchange for increased CPU utilization.
Various compression algorithms are supported, with various strengths. Our testing has shown that lzma works best with our use cases. You can read more at [Django-Redis Compression Support](https://github.com/jazzband/django-redis#compression-support) Various compression algorithms are supported, with various strengths. Our testing has shown that lzma works best with our use cases. You can read more at [Django-Redis Compression Support](https://github.com/jazzband/django-redis#compression-support)

View File

@ -0,0 +1,203 @@
# SQL
SQL Tuning is usually the realm of experienced Database Admins, as it can be full of missteps leading to worse performance. It is _extremely_ important that you take it slowly, make one change at a time with dedicated research and test before and after.
Before you start down this path its best to update [MariaDB](https://mariadb.org/download/?t=repo-config) / MySQL. Performance Schemas, some default tuning and other general performance improvements are only available on new versions. You must also allow your server to run for 24 hours at least to gather accurate data.
## MySQLTuner
[MySQLTuner](https://github.com/major/MySQLTuner-perl) is a Perl script that will analyze inbuilt metrics and spit out recommendations.
### [performance_schema](https://mariadb.com/kb/en/performance-schema-system-variables/#performance_schema)
This should be ON for 24 hours before applying any recommendations, then can be turned _OFF_ to save Memory while its not needed.
```bash
-------- Performance schema ------------------------------------------------------------------------
[--] Performance_schema is activated.
[--] Memory used by Performance_schema: 105.7M
[--] Sys schema is installed.
# 105M could be significant depending on your hardware
```
## SQL Variables
### [skip-name-resolve](https://mariadb.com/kb/en/server-system-variables/#skip_name_resolve)
While on, SQL will perform a dns resolve for all connections, if your database is connected via IP, this will save you a handful of cpu cycles per connection.
Note you must use 127.0.0.1 for localhost connections, and all entries in GRANT tables (permissions), must use IP addresses.
### [table_definition_cache](https://mariadb.com/kb/en/server-system-variables/#table_definition_cache)
Will usually need to be expanded on installs with many extensions
Most installs should cache all their tables, but if your hit rate is still quite high, you may have a lot of rarely used tables that you don't need to waste memory caching.
```bash
[OK] Table cache hit rate: 63% (2K hits / 4K requests).
# Only 63% of our queries are using this cache
table_definition_cache (400) > 567 or -1 (autosizing if supported)
# Here We have 567 tables, but a default cache of only 400.
```
```bash
[OK] Table cache hit rate: 99% (372M hits / 372M requests)
[OK] table_definition_cache (600) is greater than number of tables (567)
# Much better
```
### [innodb_buffer_pool_size](https://mariadb.com/kb/en/innodb-system-variables/#innodb_buffer_pool_size)
This is in short, the amount of memory assigned to store data for faster reads. If you are memory starved you should not increase this variable regardless of the suggestions of this tool. Pushing SQL cache to pagefile will not result in faster queries.
If you are not memory starved, you can wind this up to the amount of total data you have to store it all in memory. This would be a significant performance increase for larger installs on dedicated hardware with memory to spare.
```bash
[!!] InnoDB buffer pool / data size: 128.0M / 651.6M
# I have 651mb of _possible_ data to cache.
# We won't and shouldn't cache it all unless we have excess memory to spare.
...
[!!] InnoDB Read buffer efficiency: 0% (-2019 hits / 0 total)
# A low ratio here would suggest more Memory can be used effectively.
# A high ratio might mean we have most of our regularly used data cached already
```
### [innodb_log_buffer_size](https://mariadb.com/kb/en/innodb-system-variables/#innodb_log_buffer_size) / [innodb_log_file_size](https://mariadb.com/kb/en/innodb-system-variables/#innodb_log_file_size)
[innodb_log_file_size](https://mariadb.com/kb/en/innodb-system-variables/#innodb_log_file_size) This is your _write_ log, used to redo any commits in the event of a crash. MySQLTuner recommends this be 1/4 of your innodb_buffer_pool / read buffer. I would not lower this past the default size.
[innodb_log_buffer_size](https://mariadb.com/kb/en/innodb-system-variables/#innodb_log_buffer_size) This is the memory buffer for the write log. Larger transactions will benefit from a larger setting.
```bash
[!!] Ratio InnoDB log file size / InnoDB Buffer pool size (75%): 96.0M \* 1 / 128.0M should be equal to 25%
# Here our write log file is 75% of our read buffer, but 96MB is the default so we probably wont shrink it further
...
[OK] InnoDB Write Log efficiency: 99.11% (23167614 hits / 23375465 total) # Our transactions are typically not large enough to exhaust the write log buffer,
[OK] InnoDB log waits: 0.00% (0 waits / 207851 writes)
```
### [innodb_file_per_table](https://mariadb.com/kb/en/innodb-system-variables/#innodb_file_per_table)
This is not for performance, but for file system utilization and ease of use. While off all tables are stored in a single monolith file, as opposed to individual files. This is deprecated and set to ON in MariaDB 11.x
```bash
[OK] InnoDB File per table is activated
```
### [join_buffer_size](https://mariadb.com/kb/en/server-system-variables/#join_buffer_size)
It is always better to optimize a table with indexes, if you have valuable performance data and analysis please reach out to either the Alliance Auth or Community dev responsible for the data that could benefit from indexes. MySQLTuner will likely recommend increasing this number for as long as there are any queries that could benefit, regardless of their resulting performance impact.
Also keep in mind this is _per thread_, if you have a potential 200 connections, 256KB * 200 = 50MB, scaling this setting out too far can result in more memory use than expected.
```bash
[!!] Joins performed without indexes: 67646
```
```bash
[OK] No joins without indexes
# An ideal scenario. With well designed apps this is possible with a default join buffer.
```
### [tmp_table_size](https://mariadb.com/kb/en/server-system-variables/#tmp_table_size) / [max_heap_table_size](https://mariadb.com/kb/en/server-system-variables/#max_heap_table_size)
If a temporary table must be created due to a lack of other optimizations or large queries, it may only be stored in memory under this size. Any larger and it is performed on disk reducing performance.
tmp_table_size and max_heap_table_size should be increased together.
```bash
[!!] Temporary tables created on disk: 32% (775 on disk / 2K total)
# 32% of my temp tables are performed on disk. If you increase this size, monitor if your performance improves.
# If it does not you may have data of a certain size that is impractical to cache, and you can reclaim this memory.
```
```bash
[OK] Temporary tables created on disk: 0% (5K on disk / 4M total)
# Here only a miniscule amount of my temp tables are done on disk. No action required
```
### key_buffer_size
Index buffer for MyISAM tables, If you use no or very little data in MyISAM tables. You may reclaim some memory here
In this example we still have some MyISAM tables, you may have none
```bash
[--] General MyIsam metrics:
[--] +-- Total MyISAM Tables : 67
[--] +-- Total MyISAM indexes : 7.1M
[--] +-- KB Size :8.0M
[--] +-- KB Used Size :1.5M
[--] +-- KB used :18.3%
[--] +-- Read KB hit rate: 0% (0 cached / 0 reads)
[--] +-- Write KB hit rate: 0% (0 cached / 0 writes)
[!!] Key buffer used: 18.3% (1.5M used / 8.0M cache) # We have only filled 1.5M of the 8 assigned
[OK] Key buffer size / total MyISAM indexes: 8.0M/7.1M # This is the max theoretical buffer to cache all my indexes
Variables to adjust:
key_buffer_size (~ 1M)
# Tuner has seen that we barely use this buffer and it can be shrunk, if you care about its impact don't lower this below your total indexes.
```
### [aria_pagecache_buffer_size](https://mariadb.com/kb/en/aria-system-variables/#aria_pagecache_buffer_size)
Index and data buffer for Aria tables, If you use no or very little data in Aria tables. You may reclaim some memory here
```bash
-------- Aria Metrics ------------------------------------------------------------------------------
[--] Aria Storage Engine is enabled.
[OK] Aria pagecache size / total Aria indexes: 128.0M/328.0K # i use a fraction of my aria buffer since i have no aria tables.
[OK] Aria pagecache hit rate: 99.9% (112K cached / 75 reads) # Aria is used internally for MariaDB, so you still want an incredibly high ratio here.
```
## Swappiness
Swappiness is not an SQL variable but part of your system kernel. Swappiness controls how much free memory a server "likes" to have at any given time, and how frequently it shifts data to swapfile in order to free up memory. Desktop operating systems will have this value set quite high, whereas servers are less aggressive with their swapfile.
Database workloads especially benefit from having their caches stay in memory and will recommend values under 10 for a dedicated database server. 10 is a good compromise for a mixed use server with adequate memory.
If your server is memory starved, leave swapfile aggressive to ensure it is moving memory around as needed.
```bash
joel@METABOX:~/aa_dev$ free -m
total used free shared buff/cache available
Mem: 15998 1903 13372 2 722 13767
Swap: 4096 1404 2691
# Here we can see a lot of memory page (1404MB) sitting in swap while there is free memory (13372MB) available
```
```bash
[root@auth ~]# free -m
total used free shared buff/cache available
Mem: 738 611 59 1 68 35
Swap: 2047 1014 1033
# Here we can see a memory starved server highly utilizing swap already. I wouldn't mess with it too much. (vm.swappiness is 30)
```
```bash
[root@mysql ~]# free -m
total used free shared buff/cache available
Mem: 738 498 95 7 145 120
Swap: 2047 289 1758
# Here we can see a dedicated single use Database Server, Swappiness is 10 here because we have been careful not to starve it of memory and there is low potential to impact other applications
```
```bash
[--] Information about kernel tuning:
...
[--] vm.swappiness = 30
[xx] Swappiness is < 10.
...
vm.swappiness <= 10 (echo 10 > /proc/sys/vm/swappiness) or vm.swappiness=10 in /etc/sysctl.conf
```
## Max Asynchronous IO
Unless you are still operating on spinning rust (Hard Disk Drives), or an IO limited VPS, you can likely increase this value. Database workloads appreciate the additional scaling.
```bash
[--] Information about kernel tuning:
[--] fs.aio-max-nr = 65536
...
fs.aio-max-nr > 1M (echo 1048576 > /proc/sys/fs/aio-max-nr) or fs.aio-max-nr=1048576 in /etc/sysctl.conf
```

View File

@ -62,16 +62,15 @@ dependencies = [
test = [ test = [
"coverage>=4.3.1", "coverage>=4.3.1",
"django-webtest", "django-webtest",
"requests-mock>=1.2.0", "requests-mock>=1.2.0"
] ]
docs = [ docs = [
"sphinx>=4.4.0,<5.0.0", "sphinx",
"sphinx_rtd_theme>=1.0.0,<2.0.0", "sphinx_rtd_theme>=1.0.0,<2.0.0",
"recommonmark==0.7.1", "myst-parser",
"Jinja2<3.1", "sphinxcontrib-django",
"docutils==0.16", "sphinx-copybutton",
"sphinxcontrib-django2", "sphinx-tabs",
"sphinx-copybutton"
] ]
[project.scripts] [project.scripts]

View File

@ -27,8 +27,6 @@ commands =
[testenv:docs] [testenv:docs]
description = invoke sphinx-build to build the HTML docs description = invoke sphinx-build to build the HTML docs
basepython = python3.11 basepython = python3.11
skip_install = True install_command = pip install -e ".[docs]" -U {opts} {packages}
deps = .[docs]
install_command = python -I -m pip install {opts} {packages}
commands = commands =
sphinx-build -T -E -b html -d "{toxworkdir}/docs_doctree" -D language=en docs "{toxworkdir}/docs_out" {posargs} sphinx-build -T -E -b html -d "{toxworkdir}/docs_doctree" -D language=en docs "{toxworkdir}/docs_out" {posargs}