Compare commits

..

18 Commits

Author SHA1 Message Date
T'rahk Rokym
c9b07c12a0 Last fixes 2025-04-21 16:31:39 +02:00
T'rahk Rokym
fd84f7fe15 Doc fix 2025-04-21 16:12:00 +02:00
T'rahk Rokym
92d8c699eb Ignore closed issues 2025-04-21 16:10:58 +02:00
T'rahk Rokym
9cc3283399 Move logger statements to debug 2025-04-21 15:44:15 +02:00
T'rahk Rokym
401c093b74 Remove template hooks 2025-04-21 15:26:00 +02:00
T'rahk Rokym
b3534f4f44 Basic documentation 2025-04-21 13:16:21 +02:00
T'rahk Rokym
f88249c8fc Enable caching 2025-04-21 12:35:55 +02:00
T'rahk Rokym
ec34d7fd29 Properly translates GitHub attributes to GitLab 2025-04-21 12:35:03 +02:00
T'rahk Rokym
cd9d985732 Upgrades
- Error handling per hook
- Fix github redirect
- Better code for github pagination
2025-04-21 12:30:32 +02:00
T'rahk Rokym
1c1e219037 Basic implementation of app hooks
Still need to remove the examples and add tests
2025-04-21 01:12:40 +02:00
Joel Falknau
49a271a99f update pre-commit 2025-04-07 14:04:06 +10:00
Joel Falknau
af87da876b Celery 5.5 + shutdown timeouts 2025-04-07 14:01:33 +10:00
Joel Falknau
57b3841293 internal network port only 2025-04-07 13:57:57 +10:00
Joel Falknau
b02413c30c Type Hints 2025-03-26 13:27:01 +10:00
Joel Falknau
7ba1699dc6 Bring these in line with modern Django 2025-03-26 13:19:25 +10:00
Joel Falknau
75d67aa1b1 typehints 2025-03-26 13:18:54 +10:00
Joel Falknau
876f1e48e7 Update docs to python312, drop old OS 2025-03-06 11:28:19 +10:00
Joel Falknau
c7db4f0bd3 tox pre-commit formatter 2025-03-06 09:59:08 +10:00
33 changed files with 376 additions and 391 deletions

View File

@@ -25,13 +25,13 @@ exclude: |
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.9
rev: v0.11.4
hooks:
# Run the linter, and only the linter
- id: ruff
- repo: https://github.com/adamchainz/django-upgrade
rev: 1.23.1
rev: 1.24.0
hooks:
- id: django-upgrade
args: [--target-version=5.1]
@@ -59,7 +59,7 @@ repos:
- id: detect-private-key
- id: check-case-conflict
# Python checks
# - id: check-docstring-first
#
- id: debug-statements
# - id: requirements-txt-fixer
- id: fix-encoding-pragma
@@ -73,7 +73,7 @@ repos:
- id: check-executables-have-shebangs
- id: end-of-file-fixer
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
rev: 3.2.0
rev: 3.2.1
hooks:
- id: editorconfig-checker
- repo: https://github.com/igorshubovych/markdownlint-cli
@@ -85,18 +85,18 @@ repos:
- --disable=MD013
# Infrastructure
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.5.0
rev: v2.5.1
hooks:
- id: pyproject-fmt
name: pyproject.toml formatter
description: "Format the pyproject.toml file."
args:
- --indent=4
additional_dependencies:
- tox==4.24.1 # https://github.com/tox-dev/tox/releases/latest
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: 1.5.0
hooks:
- id: tox-ini-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
rev: v0.24.1
hooks:
- id: validate-pyproject
name: Validate pyproject.toml
description: "Validate the pyproject.toml file."

View File

@@ -32,7 +32,7 @@ class State(models.Model):
class Meta:
ordering = ['-priority']
def __str__(self):
def __str__(self) -> str:
return self.name
def available_to_character(self, character):
@@ -153,7 +153,7 @@ class CharacterOwnership(models.Model):
class Meta:
default_permissions = ('change', 'delete')
ordering = ['user', 'character__character_name']
def __str__(self):
def __str__(self) -> str:
return f"{self.user}: {self.character}"
@@ -166,5 +166,5 @@ class OwnershipRecord(models.Model):
class Meta:
ordering = ['-created']
def __str__(self):
def __str__(self) -> str:
return f"{self.user}: {self.character} on {self.created}"

View File

@@ -45,7 +45,7 @@ class CorpStats(models.Model):
def __str__(self):
def __str__(self) -> str:
return f"{self.__class__.__name__} for {self.corp}"
def update(self):
@@ -154,7 +154,7 @@ class CorpMember(models.Model):
unique_together = ('corpstats', 'character_id')
ordering = ['character_name']
def __str__(self):
def __str__(self) -> str:
return self.character_name
@property

View File

@@ -81,7 +81,7 @@ class AutogroupsConfig(models.Model):
objects = AutogroupsConfigManager()
def __str__(self):
def __str__(self) -> str:
return 'States: ' + (' '.join(list(self.states.all().values_list('name', flat=True))) if self.pk else str(None))
def __init__(self, *args, **kwargs):
@@ -235,7 +235,7 @@ class ManagedGroup(models.Model):
class Meta:
abstract = True
def __str__(self):
def __str__(self) -> str:
return f"Managed Group: {self.group.name}"
class ManagedCorpGroup(ManagedGroup):

View File

@@ -32,7 +32,7 @@ class EveFactionInfo(models.Model):
provider = providers.provider
def __str__(self):
def __str__(self) -> str:
return self.faction_name
@staticmethod
@@ -80,7 +80,7 @@ class EveAllianceInfo(models.Model):
class Meta:
indexes = [models.Index(fields=['executor_corp_id',])]
def __str__(self):
def __str__(self) -> str:
return self.alliance_name
def populate_alliance(self):
alliance = self.provider.get_alliance(self.alliance_id)
@@ -152,7 +152,7 @@ class EveCorporationInfo(models.Model):
class Meta:
indexes = [models.Index(fields=['ceo_id',]),]
def __str__(self):
def __str__(self) -> str:
return self.corporation_name
def update_corporation(self, corp: providers.Corporation = None):
if corp is None:
@@ -226,7 +226,7 @@ class EveCharacter(models.Model):
models.Index(fields=['faction_id',]),
]
def __str__(self):
def __str__(self) -> str:
return self.character_name
@property

View File

@@ -36,7 +36,7 @@ class ObjectNotFound(Exception):
self.id = obj_id
self.type = type_name
def __str__(self):
def __str__(self) -> str:
return f'{self.type} with ID {self.id} not found.'
@@ -46,7 +46,7 @@ class Entity:
self.id = id
self.name = name
def __str__(self):
def __str__(self) -> str:
return self.name
def __repr__(self):
@@ -206,7 +206,7 @@ class EveSwaggerProvider(EveProvider):
)
return self._client
def __str__(self):
def __str__(self) -> str:
return 'esi'
def get_alliance(self, alliance_id: int) -> Alliance:

View File

@@ -13,7 +13,7 @@ class BravadoResponseStub:
self.headers = headers if headers else {}
self.raw_bytes = raw_bytes
def __str__(self):
def __str__(self) -> str:
return f"{self.status_code} {self.reason}"

View File

@@ -13,7 +13,7 @@ class Fatlink(models.Model):
hash = models.CharField(max_length=254, unique=True)
creator = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
def __str__(self):
def __str__(self) -> str:
return self.fleet
@@ -28,5 +28,5 @@ class Fat(models.Model):
class Meta:
unique_together = (('character', 'fatlink'),)
def __str__(self):
def __str__(self) -> str:
return f"Fat-link for {self.character.character_name}"

View File

@@ -15,7 +15,7 @@ class GroupRequest(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
def __str__(self):
def __str__(self) -> str:
return self.user.username + ":" + self.group.name
@property
@@ -50,7 +50,7 @@ class RequestLog(models.Model):
request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
def __str__(self) -> str:
return self.pk
def requestor(self):
@@ -179,7 +179,7 @@ class AuthGroup(models.Model):
)
default_permissions = ()
def __str__(self):
def __str__(self) -> str:
return self.group.name
def group_request_approvers(self) -> set[User]:

View File

@@ -13,7 +13,7 @@ class ApplicationQuestion(models.Model):
help_text = models.CharField(max_length=254, blank=True)
multi_select = models.BooleanField(default=False)
def __str__(self):
def __str__(self) -> str:
return "Question: " + self.title
@@ -21,7 +21,7 @@ class ApplicationChoice(models.Model):
question = models.ForeignKey(ApplicationQuestion,on_delete=models.CASCADE,related_name="choices")
choice_text = models.CharField(max_length=200, verbose_name='Choice')
def __str__(self):
def __str__(self) -> str:
return self.choice_text
@@ -29,7 +29,7 @@ class ApplicationForm(models.Model):
questions = SortedManyToManyField(ApplicationQuestion)
corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE)
def __str__(self):
def __str__(self) -> str:
return str(self.corp)
@@ -50,7 +50,7 @@ class Application(models.Model):
('view_apis', 'Can view applicant APIs'),)
unique_together = ('form', 'user')
def __str__(self):
def __str__(self) -> str:
return str(self.user) + " Application To " + str(self.form)
@property
@@ -77,7 +77,7 @@ class ApplicationResponse(models.Model):
answer = models.TextField()
class Meta:
unique_together = ('question', 'application')
def __str__(self):
def __str__(self) -> str:
return str(self.application) + " Answer To " + str(self.question)
@@ -89,5 +89,5 @@ class ApplicationComment(models.Model):
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
def __str__(self) -> str:
return str(self.user) + " comment on " + str(self.application)

View File

@@ -19,7 +19,7 @@ class OpTimerType(models.Model):
ordering = ['type']
default_permissions = ()
def __str__(self):
def __str__(self) -> str:
return self.type
class OpTimer(models.Model):
@@ -39,5 +39,5 @@ class OpTimer(models.Model):
class Meta:
ordering = ['start']
default_permissions = ()
def __str__(self):
def __str__(self) -> str:
return self.operation_name

View File

@@ -1,22 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name}}.settings.local")
def main() -> None:
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as err:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django # noqa: F401
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from err
raise
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

View File

@@ -8,6 +8,7 @@ from django.utils.functional import cached_property
from allianceauth.hooks import get_hooks
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.templatetags.admin_status import AppAnnouncementHook
from .models import NameFormatConfig
@@ -119,7 +120,7 @@ class ServicesHook:
"""
return ''
def __str__(self):
def __str__(self) -> str:
return self.name or 'Unknown Service Module'
class Urls:
@@ -145,6 +146,16 @@ class MenuItemHook(MenuItemHook):
def __init_subclass__(cls) -> None:
return super().__init_subclass__()
class AppAnnouncementHook(AppAnnouncementHook):
"""
AppAnnouncementHook shim to allianceauth.templatetags.admin_status
:param AppAnnouncementHook: _description_
:type AppAnnouncementHook: _type_
"""
def __init_subclass__(cls) -> None:
return super().__init_subclass__()
class UrlHook:
"""A hook for registering the URLs of a Django app.

View File

@@ -26,7 +26,7 @@ class NameFormatConfig(models.Model):
"formatter for each state for each service."
)
def __str__(self):
def __str__(self) -> str:
return '{}: {}'.format(
self.service_name, ', '.join([str(x) for x in self.states.all()])
)

View File

@@ -16,5 +16,5 @@ class DiscourseUser(models.Model):
("access_discourse", "Can access the Discourse service"),
)
def __str__(self):
def __str__(self) -> str:
return self.user.username

View File

@@ -18,7 +18,7 @@ class SrpFleetMain(models.Model):
class Meta:
permissions = (('access_srp', 'Can access SRP module'),)
def __str__(self):
def __str__(self) -> str:
return self.fleet_name
@property
@@ -46,5 +46,5 @@ class SrpUserRequest(models.Model):
srp_ship_name = models.CharField(max_length=254, default="")
post_time = models.DateTimeField(default=timezone.now)
def __str__(self):
def __str__(self) -> str:
return self.character.character_name + ' SRP request for ' + self.srp_ship_name

View File

@@ -46,6 +46,30 @@
</div>
{% endif %}
{% if application_notifications %}
<div id="aa-dashboard-panel-admin-application-notifications" class="col-12 mb-3">
<div class="card">
<div class="card-body">
{% translate "Application Notifications" as widget_title %}
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
<div>
<ul class="list-group">
{% for notif in application_notifications %}
<li class="list-group-item">
<span class="badge bg-success me-2">{% translate "Open" %}</span>
<span class="badge bg-info me-2">{{ notif.app_name }}</span>
<a href="{{ notif.web_url }}" target="_blank">#{{ notif.iid }} {{ notif.title }}</a>
</li>
{% endfor %}
</ul>
{# TODO maybe add some disclaimer that those are managed by application devs? #}
</div>
</div>
</div>
</div>
{% endif %}
<div class="col-12 mb-3">
<div class="card">
<div class="card-body row">

View File

@@ -1,4 +1,7 @@
import logging
from dataclasses import dataclass
from enum import Enum
from urllib.parse import quote_plus
import requests
from packaging.version import InvalidVersion, Version as Pep440Version
@@ -11,6 +14,7 @@ from allianceauth import __version__
from allianceauth.authentication.task_statistics.counters import (
dashboard_results,
)
from allianceauth.hooks import get_hooks
register = template.Library()
@@ -32,6 +36,72 @@ GITLAB_AUTH_ANNOUNCEMENT_ISSUES_URL = (
logger = logging.getLogger(__name__)
@dataclass
class AppAnnouncementHook:
"""
A hook for an application to send GitHub/GitLab issues as announcements on the dashboard
Args:
- app_name: The name of your application
- repository_namespace: The namespace of the remote repository of your application source code.
It should look like `<username>/<application_name>`.
- repository_kind: Enumeration to determine if your repository is a GitHub or GitLab repository.
- label: The label applied to issues that should be seen as announcements, case-sensitive.
Default value: `announcement`
"""
class RepositoryKind(Enum):
"""Simple enumeration to determine which api should be called to access issues"""
GITLAB = "gitlab"
GITHUB = "github"
app_name: str
repository_namespace: str
repository_kind: RepositoryKind
label: str = "announcement"
def get_announcement_list(self) -> list:
"""
Checks the application repository to find issues with the `Announcement` tag and return their title and link to
be displayed.
"""
match self.repository_kind:
case AppAnnouncementHook.RepositoryKind.GITHUB:
announcement_list = self._get_github_announcement_list()
case AppAnnouncementHook.RepositoryKind.GITLAB:
announcement_list = self._get_gitlab_announcement_list()
case _:
return []
for announcement in announcement_list:
announcement["app_name"] = self.app_name
return announcement_list
def _get_github_announcement_list(self) -> list:
"""
Return the issue list for a GitHub repository
Will filter if the `pull_request` attribute is present
"""
raw_list = _fetch_list_from_github(
f"https://api.github.com/repos/{self.repository_namespace}/issues"
f"?labels={self.label}"
)
# Translates GitHub attributes to GitLab and filters out pull requests
clean_list = []
for element in raw_list:
if not element.get("pull_request"):
element["web_url"] = element["html_url"]
element["iid"] = element["number"]
clean_list.append(element)
return clean_list
def _get_gitlab_announcement_list(self) -> list:
"""Return the issues list for a GitLab repository"""
return _fetch_list_from_gitlab(
f"https://gitlab.com/api/v4/projects/{quote_plus(self.repository_namespace)}/issues"
f"?labels={self.label}&state=opened")
@register.simple_tag()
def decimal_widthratio(this_value, max_value, max_width) -> str:
@@ -89,8 +159,28 @@ def _current_notifications() -> dict:
else:
top_notifications = []
app_notifications = []
hooks = [fn() for fn in get_hooks("app_announcement_hook")]
for hook in hooks:
logger.debug(hook)
try:
app_notifications.extend(cache.get_or_set(
f"{hook.app_name}_notification_issues",
hook.get_announcement_list,
NOTIFICATION_CACHE_TIME,
))
except requests.HTTPError:
logger.warning("Error when getting %s notifications", hook, exc_info=True)
if app_notifications:
logger.debug(app_notifications)
application_notifications = app_notifications[:10]
else:
application_notifications = []
response = {
'notifications': top_notifications,
'application_notifications': application_notifications,
}
return response
@@ -199,3 +289,38 @@ def _fetch_list_from_gitlab(url: str, max_pages: int = MAX_PAGES) -> list:
break
return result
def _fetch_list_from_github(url: str, max_pages: int = MAX_PAGES) -> list:
"""returns a list from the GitHub API. Supports paging"""
result = []
for page in range(1, max_pages+1):
try:
request = requests.get(
url,
params={'page': page},
headers={
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28"
}
)
request.raise_for_status()
except requests.exceptions.RequestException as e:
error_str = str(e)
logger.warning(
f'Unable to fetch from GitHub API. Error: {error_str}',
exc_info=True,
)
return result
result += request.json()
logger.debug(request.json())
# https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api?apiVersion=2022-11-28
# See Example creating a pagination method
if not ('link' in request.headers and 'rel=\"next\"' in request.headers['link']):
break
return result

View File

@@ -14,6 +14,10 @@ app = Celery('myauth')
# Celery startup if it is unavailable.
app.conf.broker_connection_retry_on_startup = True
# Set a hard task execution time of 5 minutes before celery will cold restart
app.conf.worker_soft_shutdown_timeout = 300
app.conf.worker_enable_soft_shutdown_on_idle = True
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
app.config_from_object('django.conf:settings')

View File

@@ -89,8 +89,8 @@ services:
container_name: allianceauth_gunicorn
<<: [*allianceauth-base]
entrypoint: ["gunicorn", "myauth.wsgi", "--bind=0.0.0.0:8000", "--workers=3", "--timeout=120", "--max-requests=500", "--max-requests-jitter=50"]
ports:
- 8000:8000
expose:
- 8000
allianceauth_beat:
container_name: allianceauth_worker_beat

View File

@@ -0,0 +1,52 @@
# Announcement Hooks
This hook allows the issues opened on your application repository to be displayed on the alliance auth front page to
administrators.
![app_announcement_hook_example](img/app_announcement_hook_example.png)
To register an AppAnnouncementHook class, you would do the following:
```python
from allianceauth import hooks
from allianceauth.services.hooks import AppAnnouncementHook
@hooks.register('app_announcement_hook')
def announcement_hook():
return AppAnnouncementHook("Your app name", "USERNAME/REPOSITORY_NAME", AppAnnouncementHook.RepositoryKind.GITLAB)
```
```{eval-rst}
.. autoclass:: allianceauth.services.hooks.AppAnnouncementHook
:members: __init__
:undoc-members:
```
## Parameters
### app_name
The name of your application.
### repository_namespace
Here you should enter the namespace of your repository.
The structure stays the same for both GitHub and GitLab repositories. \
A repository with the url `https://gitlab.com/username/appname` will have a namespace of `username/appname`.
### repository_kind
This variable is an enumeration of the class `AppAnnouncemementHook.RepositoryKind`
It is mandatory to specify this variable so alliance auth contacts the correct API when fetching your repository issues.
```{eval-rst}
.. autoclass:: allianceauth.services.hooks.AppAnnouncementHook.RepositoryKind
:members: GITLAB, GITHUB
:undoc-members:
```
### label
The label that will determine if issues should be seen as an announcement.
This value is case-sensitive and the default value is `"announcement"`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -8,6 +8,7 @@ This section describes how to extend **Alliance Auth** with custom apps, service
integrating-services
menu-hooks
url-hooks
app-announcement-hooks
logging
custom-themes
aa-framework

View File

@@ -67,13 +67,13 @@ sudo apt-get install gettext
Next, we need to install Python and related development tools.
:::{note}
Should your Ubuntu come with a newer version of Python we recommend to still set up 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 set up your dev environment with the oldest Python 3 version currently supported by AA (e.g., Python 3.10 at this time of writing) to ensure your apps are compatible with all current AA installations
You can 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 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 commands below to install appopriate versions of those packages, for example, using Python 3.10 you might need to run the following after using the setup steps for the repository mentioned in the AskUbuntu post above:
```shell
sudo apt-get install python3.8 python3.8-dev python3.8-venv python3-setuptools python3-pip python-pip
sudo apt-get install python3.10 python3.10-dev python3.10-venv python3-setuptools python3-pip python-pip
```
:::

View File

@@ -17,14 +17,14 @@ This guide is currently for Ubuntu only.
The mumble server package can be retrieved from a repository, which we need to add:
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-add-repository ppa:mumble/release
```
:::
:::{group-tab} CentOS 7, Stream 8, Stream 9
:::{group-tab} CentOS Stream 9, 10
sudo yum install epel-release
sudo yum update
@@ -35,14 +35,14 @@ sudo yum update
Now three packages need to be installed:
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-get install software-properties-common mumble-server libqt5sql5-mysql
```
:::
:::{group-tab} CentOS 7, Stream 8, Stream 9
:::{group-tab} CentOS Stream 9, 10
sudo yum install mumble-server

View File

@@ -24,28 +24,14 @@ BROADCAST_SERVICE_NAME = "broadcast"
Openfire require a Java 8 runtime environment.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-get install openjdk-11-jre
```
:::
:::{group-tab} CentOS 7
```shell
sudo yum install java-11-openjdk java-11-openjdk-devel
```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo dnf install java-11-openjdk java-11-openjdk-devel
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
sudo dnf install java-11-openjdk java-11-openjdk-devel
@@ -73,18 +59,10 @@ cd ~
Download and install the package, replacing the URL with the latest you got from the Openfire download page earlier
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204
:::{group-tab} Ubuntu 2204, 2404
:::
:::{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
:::
:::{group-tab} CentOS Stream 8
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
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
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
:::

View File

@@ -14,11 +14,10 @@ Alliance Auth can be installed on any in-support *nix operating system.
Our install documentation targets the following operating systems.
- Ubuntu 20.04 - Not Recommended for new installs
- Ubuntu 22.04
- Centos 7
- CentOS Stream 8
- Ubuntu 22.04 (New installs please use 2404)
- Ubutnu 24.04
- CentOS Stream 9
- CentOS Stream 10
To install on your favorite flavour of Linux, identify and install equivalent packages to the ones listed here.
@@ -27,7 +26,7 @@ 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.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-get update
@@ -36,24 +35,7 @@ sudo do-dist-upgrade
```
:::
:::{group-tab} CentOS 7
```shell
yum install epel-release
sudo yum upgrade
```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo dnf config-manager --set-enabled powertools
sudo dnf install epel-release epel-next-release
sudo yum upgrade
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
sudo dnf config-manager --set-enabled crb
@@ -66,58 +48,33 @@ sudo yum upgrade
### Python
Install Python 3.11 and related tools on your system.
Install Python 3.12 and related tools on your system.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 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
sudo apt-get install python3.12 python3.12-dev python3.12-venv
```
:::
:::{group-tab} CentOS 7
We need to build Python from source
:::{group-tab} Ubuntu 2404
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz
tar xvf Python-3.11.7.tgz
cd Python-3.11.7/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```shell
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
sudo apt-get install python3.12 python3.12-dev python3.12-venv
```
:::
:::{group-tab} CentOS Stream 8
We need to build Python from source
:::{group-tab} CentOS Stream 9, 10
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz
tar xvf Python-3.11.7.tgz
cd Python-3.11.7/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```
sudo dnf update
sudo dnf install python3.12 python3.12-dev python3.12-venv
:::
:::{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.7/Python-3.11.7.tgz
tar xvf Python-3.11.7.tgz
cd Python-3.11.7/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```
:::
@@ -128,32 +85,24 @@ sudo make altinstall
It's recommended to use a database service instead of SQLite. Many options are available, but this guide will use MariaDB 10.11
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
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.
:::{group-tab} Ubuntu 2204
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=22.04+%22noble%22&v=11.4> to add the MariaDB repository to your host.
```shell
sudo apt-get install mariadb-server mariadb-client libmysqlclient-dev
```
:::
:::{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.
:::{group-tab} Ubuntu 2404
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=24.04+%22noble%22&v=11.4> to add the MariaDB repository to your host.
```shell
sudo yum install MariaDB-server MariaDB-client MariaDB-devel MariaDB-shared
sudo apt-get install mariadb-server mariadb-client libmysqlclient-dev
```
:::
:::{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.
```shell
sudo dnf install mariadb mariadb-server mariadb-devel
```
:::
:::{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.
:::{group-tab} CentOS Stream 9, 10
Follow the instructions at <https://mariadb.org/download/?t=repo-config&d=CentOS+Stream&v=11.4> to add the MariaDB repository to your host.
```shell
sudo dnf install mariadb mariadb-server mariadb-devel
@@ -164,16 +113,10 @@ sudo dnf install mariadb mariadb-server mariadb-devel
:::::{important}
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
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
:::{group-tab} CentOS Stream 9, 10
If you don't plan on running the database on the same server as auth you still need to install the `mariadb-devel` package
:::
::::
@@ -185,9 +128,10 @@ A few extra utilities are also required for the installation of packages.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-get install lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
@@ -195,32 +139,13 @@ sudo apt-get update
sudo apt-get install unzip git redis-server curl libssl-dev libbz2-dev libffi-dev build-essential pkg-config
```
:::
:::{group-tab} CentOS 7
```shell
sudo yum install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget pkg-config
```
```shell
sudo systemctl enable redis.service
sudo systemctl start redis.service
sudo systemctl enable redis-server
sudo systemctl start redis-server
```
:::
:::{group-tab} CentOS Stream 8
```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
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
sudo dnf install gcc gcc-c++ unzip git redis curl bzip2-devel openssl-devel libffi-devel wget
@@ -282,28 +207,15 @@ mysql_secure_installation
For security and permissions, it's highly recommended you create a separate user to install auth under. Do not log in as this account.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo adduser --disabled-login allianceserver --shell /bin/bash
```
:::
:::{group-tab} CentOS 7
```shell
sudo passwd -l allianceserver
```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo passwd -l allianceserver
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
sudo passwd -l allianceserver
@@ -354,7 +266,7 @@ Your python3.x command/version may vary depending on your installed python versi
:::
```shell
python3.11 -m venv /home/allianceserver/venv/auth/
python3.12 -m venv /home/allianceserver/venv/auth/
```
:::{tip}
@@ -497,44 +409,14 @@ exit
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-get install supervisor
```
:::
:::{group-tab} CentOS 7
```shell
sudo dnf install supervisor
```
```shell
sudo systemctl enable supervisord.service
```
```shell
sudo systemctl start supervisord.service
```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo dnf install supervisor
```
```shell
sudo systemctl enable supervisord.service
```
```shell
sudo systemctl start supervisord.service
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
sudo dnf install supervisor
@@ -554,28 +436,14 @@ 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.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisor/conf.d/myauth.conf
```
:::
:::{group-tab} CentOS 7
```shell
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
:::{group-tab} CentOS Stream 9, 10
```shell
sudo ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini

View File

@@ -10,28 +10,14 @@ If you're using a small VPS to host services with very limited memory, consider
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
apt-get install apache2
```
:::
:::{group-tab} CentOS 7
```shell
yum install httpd
```
:::
:::{group-tab} CentOS Stream 8
```shell
dnf install httpd
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
systemctl enable httpd
@@ -41,8 +27,6 @@ systemctl start httpd
:::
::::
CentOS 7, Stream 8, Stream 9
## Configuration
### Permissions
@@ -50,28 +34,14 @@ CentOS 7, Stream 8, Stream 9
Apache needs to be able to read the folder containing your auth project's static files.
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
chown -R www-data:www-data /var/www/myauth/static
```
:::
:::{group-tab} CentOS 7
```shell
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
:::{group-tab} CentOS Stream 9, 10
```shell
chown -R apache:apache /var/www/myauth/static
@@ -87,7 +57,7 @@ Apache serves sites through defined virtual hosts. These are located in `/etc/ap
A virtual host for auth needs only proxy requests to your WSGI server (Gunicorn if you followed the installation guide) and serve static files. Examples can be found below. Create your config in its own file e.g. `myauth.conf`
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
To proxy and modify headers a few mods need to be enabled.
```shell
@@ -98,13 +68,7 @@ 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`.
:::
:::{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
:::{group-tab} CentOS Stream 9, 10
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`.
:::
::::

View File

@@ -42,28 +42,14 @@ You will need to have [Gunicorn](gunicorn.md) or some other WSGI server setup fo
## Install
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo apt-get install nginx
```
:::
:::{group-tab} CentOS 7
```shell
sudo yum install nginx
```
:::
:::{group-tab} CentOS Stream 8
```shell
sudo dnf install nginx
```
:::
:::{group-tab} CentOS Stream 9
:::{group-tab} CentOS Stream 9, 10
```shell
sudo dnf install nginx

View File

@@ -14,62 +14,29 @@ To run AA with a newer Python 3 version than your system's default, you need to
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.
:::{note}
Ubuntu 2204 ships with Python 3.10 already
:::
Centos Stream 8/9:
:::{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 necessary
sudo dnf install python39 python39-devel
:::
::::{tabs}
:::{group-tab} Ubuntu 2004, 2204, 2404
:::{group-tab} Ubuntu 2204, 2404
```shell
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
sudo apt-get install python3.11 python3.11-dev python3.11-venv
sudo apt-get install python3.12 python3.12-dev python3.12-venv
```
:::
:::{group-tab} CentOS 7
:::{group-tab} Ubuntu 2404
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz
tar xvf Python-3.11.7.tgz
cd Python-3.11.7/
./configure --enable-optimizations --enable-shared
sudo make altinstall
```shell
sudo apt-get update
sudo apt-get install python3.12 python3.12-dev python3.12-venv
```
:::
:::{group-tab} CentOS Stream 8
:::{group-tab} CentOS Stream 9, 10
```bash
cd ~
sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
wget https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz
tar xvf Python-3.11.7.tgz
cd Python-3.11.7/
./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.7/Python-3.11.7.tgz
tar xvf Python-3.11.7.tgz
cd Python-3.11.7/
./configure --enable-optimizations --enable-shared
sudo make altinstall
sudo dnf update
sudo dnf install python3.12 python3.12-dev python3.12-venv
```
:::
@@ -201,10 +168,10 @@ mv /home/allianceserver/venv/auth /home/allianceserver/venv/auth_old
## Create your new venv
Now let's create our new venv with Python 3.11 and activate it:
Now let's create our new venv with Python 3.12 and activate it:
```shell
python3.11 -m venv /home/allianceserver/venv/auth
python3.12 -m venv /home/allianceserver/venv/auth
```
```shell

View File

@@ -40,7 +40,7 @@ dynamic = [
dependencies = [
"bcrypt",
"beautifulsoup4",
"celery>=5.4,<6",
"celery>=5.5,<6",
"celery-once>=3.0.1",
"django>=5.1,<5.2",
"django-bootstrap-form",

View File

@@ -1,21 +1,23 @@
#!/usr/bin/env python
"""
Django's command-line utility for administrative tasks.
Modified to insert Tests as the first argument
"""
import sys
if __name__ == "__main__":
def main() -> None:
"""Run tests"""
try:
from django.core.management import execute_from_command_line
except ImportError as err:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django # noqa: F401
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from err # Provide context for the original error
raise # Re-raise original exception with context
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv.insert(1, "test"))
if __name__ == '__main__':
main()

25
tox.ini
View File

@@ -1,30 +1,33 @@
[tox]
isolated_build = true
skipsdist = true
requires =
tox>=4.2
env_list =
docs
py{313, 312, 311, 310}-{all, core}
no_package = true
usedevelop = true
envlist = py{310,311,312,313}-{all,core}, docs
[testenv]
setenv =
all: DJANGO_SETTINGS_MODULE = tests.settings_all
core: DJANGO_SETTINGS_MODULE = tests.settings_core
basepython =
base_python =
py310: python3.10
py311: python3.11
py312: python3.12
py313: python3.13
deps=
deps =
coverage
install_command = pip install -e ".[test]" -U {opts} {packages}
set_env =
all: DJANGO_SETTINGS_MODULE = tests.settings_all
core: DJANGO_SETTINGS_MODULE = tests.settings_core
commands =
all: coverage run runtests.py -v 2 --debug-mode
core: coverage run runtests.py allianceauth.authentication.tests.test_app_settings -v 2 --debug-mode
all: coverage report -m
all: coverage xml
install_command = pip install -e ".[test]" -U {opts} {packages}
[testenv:docs]
description = invoke sphinx-build to build the HTML docs
basepython = python3.12
install_command = pip install -e ".[docs]" -U {opts} {packages}
base_python = python3.12
commands =
sphinx-build -T -E -b html -d "{toxworkdir}/docs_doctree" -D language=en docs "{toxworkdir}/docs_out" {posargs}
install_command = pip install -e ".[docs]" -U {opts} {packages}