mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-12 01:56:25 +01:00
Compare commits
48 Commits
v4.6.2a
...
9dad53f763
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dad53f763 | ||
|
|
2d57064a7a | ||
|
|
833d12cf66 | ||
|
|
7b56caa4cb | ||
|
|
5752644122 | ||
|
|
cadc0cb534 | ||
|
|
dcdab5ae1f | ||
|
|
d64e896288 | ||
|
|
500d8ede32 | ||
|
|
f4c5c7f6db | ||
|
|
43e1be4032 | ||
|
|
702def2a4d | ||
|
|
a34baf4154 | ||
|
|
4de0774f15 | ||
|
|
83d2dfc7d9 | ||
|
|
c93afd2d68 | ||
|
|
b7bacd11af | ||
|
|
f26835fae0 | ||
|
|
4edb7cb678 | ||
|
|
2ce9ba997f | ||
|
|
055077fa77 | ||
|
|
f342ccbc6a | ||
|
|
37ffd0a1ac | ||
|
|
a1f705381e | ||
|
|
c0970ad4fa | ||
|
|
3818d0c6d1 | ||
|
|
95411c79cb | ||
|
|
eeccbbacfc | ||
|
|
f6c4180502 | ||
|
|
f4d3d6c0b1 | ||
|
|
e9d2d11297 | ||
|
|
96204b29e8 | ||
|
|
47842c1243 | ||
|
|
9b494106bc | ||
|
|
d51e730a7f | ||
|
|
363909c0c4 | ||
|
|
82273f68fe | ||
|
|
12fa38b446 | ||
|
|
c26af593ff | ||
|
|
8e9a53c494 | ||
|
|
5559ce5fbb | ||
|
|
faa529a55b | ||
|
|
4ccfe20c14 | ||
|
|
3acb651650 | ||
|
|
2de57b334b | ||
|
|
0498f5bb1b | ||
|
|
929485a8f9 | ||
|
|
28cb62f373 |
@@ -5,7 +5,7 @@ manage online service access.
|
||||
# This will make sure the app is always imported when
|
||||
# Django starts so that shared_task will use this app.
|
||||
|
||||
__version__ = '4.6.2a'
|
||||
__version__ = '4.6.4'
|
||||
__title__ = 'Alliance Auth'
|
||||
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
||||
NAME = f'{__title__} v{__version__}'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from django.apps import apps
|
||||
from allianceauth.authentication.models import User
|
||||
from allianceauth.analytics.utils import install_stat_users, install_stat_addons
|
||||
from esi.models import Token
|
||||
from allianceauth.analytics.utils import install_stat_users, install_stat_tokens, install_stat_addons
|
||||
|
||||
from django.test.testcases import TestCase
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from django.urls import include
|
||||
from django.contrib.auth.decorators import user_passes_test
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from functools import wraps
|
||||
from typing import Callable, Iterable, Optional
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.db import models, transaction
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo, EveAllianceInfo, EveFactionInfo
|
||||
from allianceauth.notifications import notify
|
||||
from django.conf import settings
|
||||
|
||||
from .managers import CharacterOwnershipManager, StateManager
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
{% load theme_tags %}
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="en" {% theme_html_tags %}>
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<!-- TODO Bundle all the site specific stuff up into its own template for easy override -->
|
||||
<meta property="og:title" content="{{ SITE_NAME }}">
|
||||
<meta property="og:image" content="{{ SITE_URL }}{% static 'allianceauth/icons/apple-touch-icon.png' %}">
|
||||
<meta property="og:description" content="Alliance Auth - An auth system for EVE Online to help in-game organizations manage online service access.">
|
||||
<!-- End Required meta tags -->
|
||||
|
||||
<!-- Meta tags -->
|
||||
{% include 'allianceauth/opengraph.html' %}
|
||||
{% include 'allianceauth/icons.html' %}
|
||||
<!-- Meta tags -->
|
||||
|
||||
<title>{% block title %}{% block page_title %}{% endblock page_title %} - {{ SITE_NAME }}{% endblock title %}</title>
|
||||
|
||||
{% theme_css %}
|
||||
|
||||
{% include 'bundles/fontawesome.html' %}
|
||||
{% include 'bundles/auth-framework-css.html' %}
|
||||
|
||||
{% block extra_include %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
from django.db.models.signals import (
|
||||
m2m_changed,
|
||||
post_save,
|
||||
pre_delete,
|
||||
pre_save
|
||||
)
|
||||
from django.urls import reverse
|
||||
from unittest import mock
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from unittest import mock
|
||||
from allianceauth.authentication.middleware import UserSettingsMiddleware
|
||||
from unittest.mock import Mock
|
||||
from django.http import HttpResponse
|
||||
|
||||
@@ -4,10 +4,16 @@ from allianceauth.eveonline.models import (
|
||||
EveCorporationInfo,
|
||||
EveAllianceInfo
|
||||
)
|
||||
from django.db.models.signals import post_save
|
||||
from django.db.models.signals import (
|
||||
pre_save,
|
||||
post_save,
|
||||
pre_delete,
|
||||
m2m_changed
|
||||
)
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from django.test.testcases import TestCase
|
||||
from unittest.mock import Mock
|
||||
from . import patch
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import authenticate, login
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.contrib.auth.models import User
|
||||
from django.core import signing
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import redirect, render
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
Django system checks for Alliance Auth
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
from django import db
|
||||
from django.core.checks import CheckMessage, Error, register, Warning
|
||||
@@ -16,48 +20,172 @@ B = Configuration
|
||||
|
||||
@register()
|
||||
def django_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
if hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL[-1] == "/":
|
||||
errors.append(Warning("'SITE_URL' Has a trailing slash. This may lead to incorrect links being generated by Auth.", hint="", id="allianceauth.checks.B005"))
|
||||
else:
|
||||
errors.append(Error("No 'SITE_URL' found is settings. This may lead to incorrect links being generated by Auth or Errors in 3rd party modules.", hint="", id="allianceauth.checks.B006"))
|
||||
"""
|
||||
Check that Django settings are correctly configured
|
||||
|
||||
if hasattr(settings, "CSRF_TRUSTED_ORIGINS") and hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL not in settings.CSRF_TRUSTED_ORIGINS:
|
||||
errors.append(Warning("'SITE_URL' not found in 'CSRF_TRUSTED_ORIGINS'. Auth may not load pages correctly until this is rectified.", hint="", id="allianceauth.checks.B007"))
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
# Check for SITE_URL
|
||||
if hasattr(settings, "SITE_URL"):
|
||||
# Check if SITE_URL is empty
|
||||
if settings.SITE_URL == "":
|
||||
errors.append(
|
||||
Error(
|
||||
msg="'SITE_URL' is empty.",
|
||||
hint="Make sure to set 'SITE_URL' to the URL of your Auth instance. (Without trailing slash)",
|
||||
id="allianceauth.checks.B011",
|
||||
)
|
||||
)
|
||||
# Check if SITE_URL has a trailing slash
|
||||
elif settings.SITE_URL[-1] == "/":
|
||||
errors.append(
|
||||
Warning(
|
||||
msg="'SITE_URL' has a trailing slash. This may lead to incorrect links being generated by Auth.",
|
||||
hint="",
|
||||
id="allianceauth.checks.B005",
|
||||
)
|
||||
)
|
||||
# SITE_URL not found
|
||||
else:
|
||||
errors.append(Error("No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified", hint="", id="allianceauth.checks.B008"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg="No 'SITE_URL' found is settings. This may lead to incorrect links being generated by Auth or Errors in 3rd party modules.",
|
||||
hint="",
|
||||
id="allianceauth.checks.B006",
|
||||
)
|
||||
)
|
||||
|
||||
# Check for CSRF_TRUSTED_ORIGINS
|
||||
if hasattr(settings, "CSRF_TRUSTED_ORIGINS") and hasattr(settings, "SITE_URL"):
|
||||
# Check if SITE_URL is not in CSRF_TRUSTED_ORIGINS
|
||||
if settings.SITE_URL not in settings.CSRF_TRUSTED_ORIGINS:
|
||||
errors.append(
|
||||
Warning(
|
||||
msg="'SITE_URL' not found in 'CSRF_TRUSTED_ORIGINS'. Auth may not load pages correctly until this is rectified.",
|
||||
hint="",
|
||||
id="allianceauth.checks.B007",
|
||||
)
|
||||
)
|
||||
# CSRF_TRUSTED_ORIGINS not found
|
||||
else:
|
||||
errors.append(
|
||||
Error(
|
||||
msg="No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified",
|
||||
hint="",
|
||||
id="allianceauth.checks.B008",
|
||||
)
|
||||
)
|
||||
|
||||
# Check for ESI_USER_CONTACT_EMAIL
|
||||
if hasattr(settings, "ESI_USER_CONTACT_EMAIL"):
|
||||
# Check if ESI_USER_CONTACT_EMAIL is empty
|
||||
if settings.ESI_USER_CONTACT_EMAIL == "":
|
||||
errors.append(
|
||||
Error(
|
||||
msg="'ESI_USER_CONTACT_EMAIL' is empty. A valid email is required as maintainer contact for CCP.",
|
||||
hint="",
|
||||
id="allianceauth.checks.B009",
|
||||
)
|
||||
)
|
||||
# ESI_USER_CONTACT_EMAIL not found
|
||||
else:
|
||||
errors.append(
|
||||
Error(
|
||||
msg="No 'ESI_USER_CONTACT_EMAIL' found is settings. A valid email is required as maintainer contact for CCP.",
|
||||
hint="",
|
||||
id="allianceauth.checks.B010",
|
||||
)
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_redis(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
"""
|
||||
Check that Redis is a supported version
|
||||
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
allianceauth_redis_install_link = "https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools"
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
try:
|
||||
redis_version = Pep440Version(get_redis_client().info()['redis_version'])
|
||||
redis_version = Pep440Version(get_redis_client().info()["redis_version"])
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm Redis Version"))
|
||||
|
||||
return errors
|
||||
|
||||
if redis_version.major == 7 and redis_version.minor == 2 and timezone.now() > timezone.datetime(year=2025, month=8, day=31, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint=allianceauth_redis_install_link, id="allianceauth.checks.A001"))
|
||||
if (
|
||||
redis_version.major == 7
|
||||
and redis_version.minor == 2
|
||||
and timezone.now()
|
||||
> timezone.datetime(year=2025, month=8, day=31, tzinfo=timezone.utc)
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"Redis {redis_version.public} in Security Support only, Updating Suggested",
|
||||
hint=allianceauth_redis_install_link,
|
||||
id="allianceauth.checks.A001",
|
||||
)
|
||||
)
|
||||
elif redis_version.major == 7 and redis_version.minor == 0:
|
||||
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint=allianceauth_redis_install_link, id="allianceauth.checks.A002"))
|
||||
errors.append(
|
||||
Warning(
|
||||
msg=f"Redis {redis_version.public} in Security Support only, Updating Suggested",
|
||||
hint=allianceauth_redis_install_link,
|
||||
id="allianceauth.checks.A002",
|
||||
)
|
||||
)
|
||||
elif redis_version.major == 6 and redis_version.minor == 2:
|
||||
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint=allianceauth_redis_install_link, id="allianceauth.checks.A018"))
|
||||
errors.append(
|
||||
Warning(
|
||||
msg=f"Redis {redis_version.public} in Security Support only, Updating Suggested",
|
||||
hint=allianceauth_redis_install_link,
|
||||
id="allianceauth.checks.A018",
|
||||
)
|
||||
)
|
||||
elif redis_version.major in [6, 5]:
|
||||
errors.append(Error(f"Redis {redis_version.public} EOL", hint=allianceauth_redis_install_link, id="allianceauth.checks.A003"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"Redis {redis_version.public} EOL",
|
||||
hint=allianceauth_redis_install_link,
|
||||
id="allianceauth.checks.A003",
|
||||
)
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
"""
|
||||
Check that MySQL is a supported version
|
||||
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
mysql_quick_guide_link = "https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/"
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
@@ -65,108 +193,302 @@ def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql":
|
||||
try:
|
||||
mysql_version = Pep440Version(".".join(str(i) for i in connection.mysql_version))
|
||||
mysql_version = Pep440Version(
|
||||
".".join(str(i) for i in connection.mysql_version)
|
||||
)
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm MySQL Version"))
|
||||
|
||||
return errors
|
||||
|
||||
# MySQL 8
|
||||
if mysql_version.major == 8:
|
||||
if mysql_version.minor == 4 and timezone.now() > timezone.datetime(year=2032, month=4, day=30, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint=mysql_quick_guide_link, id="allianceauth.checks.A004"))
|
||||
if mysql_version.minor == 4 and timezone.now() > timezone.datetime(
|
||||
year=2032, month=4, day=30, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MySQL {mysql_version.public} EOL",
|
||||
hint=mysql_quick_guide_link,
|
||||
id="allianceauth.checks.A004",
|
||||
)
|
||||
)
|
||||
elif mysql_version.minor == 3:
|
||||
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint=mysql_quick_guide_link, id="allianceauth.checks.A005"))
|
||||
errors.append(
|
||||
Warning(
|
||||
msg=f"MySQL {mysql_version.public} Non LTS",
|
||||
hint=mysql_quick_guide_link,
|
||||
id="allianceauth.checks.A005",
|
||||
)
|
||||
)
|
||||
elif mysql_version.minor == 2:
|
||||
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint=mysql_quick_guide_link, id="allianceauth.checks.A006"))
|
||||
errors.append(
|
||||
Warning(
|
||||
msg=f"MySQL {mysql_version.public} Non LTS",
|
||||
hint=mysql_quick_guide_link,
|
||||
id="allianceauth.checks.A006",
|
||||
)
|
||||
)
|
||||
elif mysql_version.minor == 1:
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint=mysql_quick_guide_link, id="allianceauth.checks.A007"))
|
||||
elif mysql_version.minor == 0 and timezone.now() > timezone.datetime(year=2026, month=4, day=30, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint=mysql_quick_guide_link, id="allianceauth.checks.A008"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MySQL {mysql_version.public} EOL",
|
||||
hint=mysql_quick_guide_link,
|
||||
id="allianceauth.checks.A007",
|
||||
)
|
||||
)
|
||||
elif mysql_version.minor == 0 and timezone.now() > timezone.datetime(
|
||||
year=2026, month=4, day=30, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MySQL {mysql_version.public} EOL",
|
||||
hint=mysql_quick_guide_link,
|
||||
id="allianceauth.checks.A008",
|
||||
)
|
||||
)
|
||||
|
||||
# MySQL below 8
|
||||
# This will also catch Mariadb 5.x
|
||||
elif mysql_version.major < 8:
|
||||
errors.append(Error(f"MySQL or MariaDB {mysql_version.public} EOL", hint=mysql_quick_guide_link, id="allianceauth.checks.A009"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MySQL or MariaDB {mysql_version.public} EOL",
|
||||
hint=mysql_quick_guide_link,
|
||||
id="allianceauth.checks.A009",
|
||||
)
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
"""
|
||||
Check that MariaDB is a supported version
|
||||
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
mariadb_download_link = "https://mariadb.org/download/?t=repo-config"
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql": # Still to find a way to determine MySQL vs MariaDB
|
||||
# TODO: Find a way to determine MySQL vs. MariaDB
|
||||
if connection.vendor == "mysql":
|
||||
try:
|
||||
mariadb_version = Pep440Version(".".join(str(i) for i in connection.mysql_version))
|
||||
mariadb_version = Pep440Version(
|
||||
".".join(str(i) for i in connection.mysql_version)
|
||||
)
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm MariaDB Version"))
|
||||
|
||||
return errors
|
||||
|
||||
# MariaDB 11
|
||||
if mariadb_version.major == 11:
|
||||
if mariadb_version.minor == 4 and timezone.now() > timezone.datetime(year=2029, month=5, day=19, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A010"))
|
||||
if mariadb_version.minor == 4 and timezone.now() > timezone.datetime(
|
||||
year=2029, month=5, day=19, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A010",
|
||||
)
|
||||
)
|
||||
elif mariadb_version.minor == 2:
|
||||
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint=mariadb_download_link, id="allianceauth.checks.A018"))
|
||||
errors.append(
|
||||
Warning(
|
||||
msg=f"MariaDB {mariadb_version.public} Non LTS",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A018",
|
||||
)
|
||||
)
|
||||
|
||||
if timezone.now() > timezone.datetime(year=2024, month=11, day=21, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A011"))
|
||||
if timezone.now() > timezone.datetime(
|
||||
year=2024, month=11, day=21, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A011",
|
||||
)
|
||||
)
|
||||
elif mariadb_version.minor == 1:
|
||||
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint=mariadb_download_link, id="allianceauth.checks.A019"))
|
||||
errors.append(
|
||||
Warning(
|
||||
msg=f"MariaDB {mariadb_version.public} Non LTS",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A019",
|
||||
)
|
||||
)
|
||||
|
||||
if timezone.now() > timezone.datetime(year=2024, month=8, day=21, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A012"))
|
||||
elif mariadb_version.minor in [0, 3]: # Demote versions down here once EOL
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A013"))
|
||||
if timezone.now() > timezone.datetime(
|
||||
year=2024, month=8, day=21, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A012",
|
||||
)
|
||||
)
|
||||
# Demote versions down here once EOL
|
||||
elif mariadb_version.minor in [0, 3]:
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A013",
|
||||
)
|
||||
)
|
||||
|
||||
# MariaDB 10
|
||||
elif mariadb_version.major == 10:
|
||||
if mariadb_version.minor == 11 and timezone.now() > timezone.datetime(year=2028, month=2, day=10, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A014"))
|
||||
elif mariadb_version.minor == 6 and timezone.now() > timezone.datetime(year=2026, month=7, day=6, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A0015"))
|
||||
elif mariadb_version.minor == 5 and timezone.now() > timezone.datetime(year=2025, month=6, day=24, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A016"))
|
||||
elif mariadb_version.minor in [0, 1, 2, 3, 4, 7, 9, 10]: # Demote versions down here once EOL
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint=mariadb_download_link, id="allianceauth.checks.A017"))
|
||||
if mariadb_version.minor == 11 and timezone.now() > timezone.datetime(
|
||||
year=2028, month=2, day=10, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A014",
|
||||
)
|
||||
)
|
||||
elif mariadb_version.minor == 6 and timezone.now() > timezone.datetime(
|
||||
year=2026, month=7, day=6, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A0015",
|
||||
)
|
||||
)
|
||||
elif mariadb_version.minor == 5 and timezone.now() > timezone.datetime(
|
||||
year=2025, month=6, day=24, tzinfo=timezone.utc
|
||||
):
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A016",
|
||||
)
|
||||
)
|
||||
# Demote versions down here once EOL
|
||||
elif mariadb_version.minor in [0, 1, 2, 3, 4, 7, 9, 10]:
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"MariaDB {mariadb_version.public} EOL",
|
||||
hint=mariadb_download_link,
|
||||
id="allianceauth.checks.A017",
|
||||
)
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_sqlite(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
"""
|
||||
Check that SQLite is a supported version
|
||||
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "sqlite":
|
||||
try:
|
||||
sqlite_version = Pep440Version(".".join(str(i) for i in sqlite_version_info))
|
||||
sqlite_version = Pep440Version(
|
||||
".".join(str(i) for i in sqlite_version_info)
|
||||
)
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm SQLite Version"))
|
||||
|
||||
return errors
|
||||
if sqlite_version.major == 3 and sqlite_version.minor < 27:
|
||||
errors.append(Error(f"SQLite {sqlite_version.public} Unsupported by Django", hint="https://pkgs.org/download/sqlite3", id="allianceauth.checks.A020"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"SQLite {sqlite_version.public} Unsupported by Django",
|
||||
hint="https://pkgs.org/download/sqlite3",
|
||||
id="allianceauth.checks.A020",
|
||||
)
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
"""
|
||||
Check that SQL settings are correctly configured
|
||||
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql":
|
||||
try:
|
||||
if connection.settings_dict["OPTIONS"]["charset"] != "utf8mb4":
|
||||
errors.append(Error(f"SQL Charset is not set to utf8mb4 DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"SQL Charset is not set to utf8mb4 DB: {connection.alias}",
|
||||
hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8",
|
||||
id="allianceauth.checks.B001",
|
||||
)
|
||||
)
|
||||
except KeyError:
|
||||
errors.append(Error(f"SQL Charset is not set to utf8mb4 DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg=f"SQL Charset is not set to utf8mb4 DB: {connection.alias}",
|
||||
hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8",
|
||||
id="allianceauth.checks.B001",
|
||||
)
|
||||
)
|
||||
|
||||
# This hasn't actually been set on AA yet
|
||||
# try:
|
||||
# if connection.settings_dict["OPTIONS"]["collation"] != "utf8mb4_unicode_ci":
|
||||
# errors.append(Error(f"SQL Collation is not set to utf8mb4_unicode_ci DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
# if (
|
||||
# connection.settings_dict["OPTIONS"]["collation"]
|
||||
# != "utf8mb4_unicode_ci"
|
||||
# ):
|
||||
# errors.append(
|
||||
# Error(
|
||||
# msg=f"SQL Collation is not set to utf8mb4_unicode_ci DB:{connection.alias}",
|
||||
# hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8",
|
||||
# id="allianceauth.checks.B001",
|
||||
# )
|
||||
# )
|
||||
# except KeyError:
|
||||
# errors.append(Error(f"SQL Collation is not set to utf8mb4_unicode_ci DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
# errors.append(
|
||||
# Error(
|
||||
# msg=f"SQL Collation is not set to utf8mb4_unicode_ci DB:{connection.alias}",
|
||||
# hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8",
|
||||
# id="allianceauth.checks.B001",
|
||||
# )
|
||||
# )
|
||||
|
||||
# if connection.vendor == "sqlite":
|
||||
|
||||
@@ -175,19 +497,57 @@ def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
@register()
|
||||
def celery_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
"""
|
||||
Check that Celery settings are correctly configured
|
||||
|
||||
:param app_configs:
|
||||
:type app_configs:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
try:
|
||||
if current_app.conf.broker_transport_options != {'priority_steps': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'queue_order_strategy': 'priority'}:
|
||||
errors.append(Error("Celery Priorities are not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc", id="allianceauth.checks.B003"))
|
||||
if current_app.conf.broker_transport_options != {
|
||||
"priority_steps": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
"queue_order_strategy": "priority",
|
||||
}:
|
||||
errors.append(
|
||||
Error(
|
||||
msg="Celery Priorities are not set correctly",
|
||||
hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc",
|
||||
id="allianceauth.checks.B003",
|
||||
)
|
||||
)
|
||||
except KeyError:
|
||||
errors.append(Error("Celery Priorities are not set", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc", id="allianceauth.checks.B003"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg="Celery Priorities are not set",
|
||||
hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc",
|
||||
id="allianceauth.checks.B003",
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
if current_app.conf.broker_connection_retry_on_startup != True:
|
||||
errors.append(Error("Celery broker_connection_retry_on_startup not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280", id="allianceauth.checks.B004"))
|
||||
if not current_app.conf.broker_connection_retry_on_startup:
|
||||
errors.append(
|
||||
Error(
|
||||
msg="Celery broker_connection_retry_on_startup not set correctly",
|
||||
hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280",
|
||||
id="allianceauth.checks.B004",
|
||||
)
|
||||
)
|
||||
except KeyError:
|
||||
errors.append(Error("Celery broker_connection_retry_on_startup not set", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280", id="allianceauth.checks.B004"))
|
||||
errors.append(
|
||||
Error(
|
||||
msg="Celery broker_connection_retry_on_startup not set",
|
||||
hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280",
|
||||
id="allianceauth.checks.B004",
|
||||
)
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@@ -40,10 +40,11 @@ class OffsetDatabaseScheduler(DatabaseScheduler):
|
||||
|
||||
for name, entry_fields in mapping.items():
|
||||
try:
|
||||
apply_offset = entry_fields.pop("apply_offset", False) # Ensure this pops before django tries to save to ORM
|
||||
apply_offset = entry_fields.pop("apply_offset", False) # Ensure this pops before django tries to save to ORM
|
||||
entry = self.Entry.from_entry(name, app=self.app, **entry_fields)
|
||||
|
||||
if apply_offset:
|
||||
entry_fields.update({"apply_offset": apply_offset}) # Reapply this as its gets pulled from config inconsistently.
|
||||
schedule_obj = entry.schedule
|
||||
if isinstance(schedule_obj, schedules.crontab):
|
||||
offset_cs = CrontabSchedule.from_schedule(offset_cron(schedule_obj))
|
||||
@@ -55,6 +56,7 @@ class OffsetDatabaseScheduler(DatabaseScheduler):
|
||||
day_of_week=offset_cs.day_of_week,
|
||||
timezone=offset_cs.timezone,
|
||||
)
|
||||
entry.schedule = offset_cron(schedule_obj) # This gets passed into Celery Beats Memory, important to keep it in sync with the model/DB
|
||||
entry.model.crontab = offset_cs
|
||||
entry.model.save()
|
||||
logger.debug(f"Offset applied for '{name}' due to 'apply_offset' = True.")
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# myapp/tests/test_tasks.py
|
||||
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
from django.test import TestCase
|
||||
|
||||
@@ -5,6 +5,9 @@ Form widgets for custom_css app
|
||||
# Django
|
||||
from django import forms
|
||||
|
||||
# Alliance Auth
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
|
||||
|
||||
class CssEditorWidget(forms.Textarea):
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db import transaction
|
||||
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from ...models import EveCharacter, EveCorporationInfo, EveAllianceInfo
|
||||
from .. import dotlan, zkillboard, evewho, eveimageserver
|
||||
from ...templatetags import evelinks
|
||||
|
||||
|
||||
class TestEveWho(TestCase):
|
||||
|
||||
@@ -723,5 +723,5 @@ class TestEveSwaggerProvider(TestCase):
|
||||
my_client = my_provider.client
|
||||
operation = my_client.Universe.get_universe_factions()
|
||||
self.assertEqual(
|
||||
operation.future.request.headers['User-Agent'], 'allianceauth v1.0.0'
|
||||
operation.future.request.headers['User-Agent'], 'allianceauth v1.0.0 dummy@example.net'
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<th class="text-center">{% translate "Character" %}</th>
|
||||
<th class="text-center">{% translate "System" %}</th>
|
||||
<th class="text-center">{% translate "Ship" %}</th>
|
||||
<th class="text-center">{% translate "Eve Time" %}</th>
|
||||
<th class="text-center">{% translate "EVE time" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<tr>
|
||||
<th class="text-center">{% translate "Fleet" %}</th>
|
||||
<th class="text-center">{% translate "Creator" %}</th>
|
||||
<th class="text-center">{% translate "Eve Time" %}</th>
|
||||
<th class="text-center">{% translate "EVE time" %}</th>
|
||||
<th class="text-center">{% translate "Duration" %}</th>
|
||||
<th class="text-center">{% translate "Edit" %}</th>
|
||||
</tr>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<th scope="col" class="text-center">{% translate "Character" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "System" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Ship" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Eve Time" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "EVE time" %}</th>
|
||||
</tr>
|
||||
|
||||
{% for fat in fats %}
|
||||
@@ -89,7 +89,7 @@
|
||||
<th scope="col" class="text-center">{% translate "Name" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Creator" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Fleet" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Eve Time" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "EVE time" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Duration" %}</th>
|
||||
<th scope="col" class="text-center">{% translate "Edit" %}</th>
|
||||
</tr>
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError, ObjectDoesNotExist
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.shortcuts import render, redirect, get_object_or_404, Http404
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from esi.decorators import token_required
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
{# {% include "framework/header/page-header.html" with title="Foobar" subtitle="Barfoo" %}#}
|
||||
|
||||
{% if title %}
|
||||
<h1 class="page-header text-center mb-3">
|
||||
{{ title }}
|
||||
<header class="aa-page-header mb-3">
|
||||
<h1 class="page-header text-center">
|
||||
{{ title }}
|
||||
|
||||
{% if subtitle %}
|
||||
<br>
|
||||
<small class="text-muted">{{ subtitle }}</small>
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% if subtitle %}
|
||||
<br>
|
||||
<small class="text-muted">{{ subtitle }}</small>
|
||||
{% endif %}
|
||||
</h1>
|
||||
</header>
|
||||
{% endif %}
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -186,7 +186,7 @@ class TestRenderDefaultMenu(TestCase):
|
||||
classes = "fa-solid fa-users-gear"
|
||||
url_name = "groupmanagement:management"
|
||||
|
||||
def render(self, request):
|
||||
def render(Self, request):
|
||||
# simulate no perms
|
||||
return ""
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import json
|
||||
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
from django.test import TestCase, RequestFactory
|
||||
from django.urls import reverse
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<th class="text-center">{% translate "Operation" %}</th>
|
||||
<th class="text-center">{% translate "Type" %}</th>
|
||||
<th class="text-center">{% translate "Form Up System" %}</th>
|
||||
<th class="text-center">{% translate "EVE Time" %}</th>
|
||||
<th class="text-center">{% translate "EVE time" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<div>
|
||||
<div class="text-center mb-3">
|
||||
<div class="badge bg-primary text-start">
|
||||
<b>{% translate "Current Eve Time:" %}</b>
|
||||
<b>{% translate "Current EVE time:" %}</b>
|
||||
<span id="current-time"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -127,8 +127,8 @@
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current Eve time as a string
|
||||
* @returns {string} Eve time string
|
||||
* Get the current EVE time as a string
|
||||
* @returns {string} EVE time string
|
||||
*/
|
||||
const updateClock = () => {
|
||||
document.getElementById("current-time").innerHTML = getCurrentEveTimeString();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import Permission, User
|
||||
from django.db.models import Count
|
||||
from django.shortcuts import render, Http404
|
||||
|
||||
|
||||
@@ -119,7 +119,12 @@ LANGUAGES = ( # Sorted by Language Code alphabetical order + English at top
|
||||
|
||||
# Django's language codes are different from some of the libraries we use,
|
||||
# so we need to map them.
|
||||
# When adding a new language, please remember to add it to the mapping
|
||||
# and add the language files to their respective directories under `allianceauth/static/allianceauth/libs/`.
|
||||
LANGUAGE_MAPPING = {
|
||||
# See https://github.com/DataTables/Plugins/tree/master/i18n for available languages
|
||||
# (We use the JSON files)
|
||||
# `allianceauth/static/allianceauth/libs/DataTables/Plugins/{version}/i18n/` for the files
|
||||
"DataTables": {
|
||||
"cs-cz": "cs",
|
||||
"de": "de-DE",
|
||||
@@ -134,6 +139,8 @@ LANGUAGE_MAPPING = {
|
||||
"uk": "uk",
|
||||
"zh-hans": "zh-HANT",
|
||||
},
|
||||
# See https://github.com/moment/moment/tree/master/locale for available languages
|
||||
# `allianceauth/static/allianceauth/libs/moment.js/{version}/locale/` for the files
|
||||
"MomentJS": {
|
||||
"cs-cz": "cs",
|
||||
"de": "de",
|
||||
|
||||
@@ -1,49 +1,48 @@
|
||||
[program:beat]
|
||||
command={{ celery }} -A {{ project_name }} beat
|
||||
directory={{ project_directory }}
|
||||
user=allianceserver
|
||||
stdout_logfile={{ project_directory }}/log/beat.log
|
||||
stderr_logfile={{ project_directory }}/log/beat.log
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startsecs=10
|
||||
priority=998
|
||||
command = {{ celery }} -A {{ project_name }} beat
|
||||
directory = {{ project_directory }}
|
||||
user = allianceserver
|
||||
stdout_logfile = {{ project_directory }}/log/%(program_name)s.log
|
||||
stderr_logfile = {{ project_directory }}/log/%(program_name)s.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
startsecs = 10
|
||||
priority = 998
|
||||
|
||||
[program:worker]
|
||||
command={{ celery }} -A {{ project_name }} worker --pool=threads --concurrency=5 -n %(program_name)s_%(process_num)02d
|
||||
directory={{ project_directory }}
|
||||
user=allianceserver
|
||||
numprocs=1
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
stdout_logfile={{ project_directory }}/log/worker.log
|
||||
stderr_logfile={{ project_directory }}/log/worker.log
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startsecs=10
|
||||
command = {{ celery }} -A {{ project_name }} worker --pool=threads --concurrency=5 -n %(program_name)s_%(process_num)02d
|
||||
directory = {{ project_directory }}
|
||||
user = allianceserver
|
||||
numprocs = 1
|
||||
process_name = %(program_name)s_%(process_num)02d
|
||||
stdout_logfile = {{ project_directory }}/log/%(program_name)s.log
|
||||
stderr_logfile = {{ project_directory }}/log/%(program_name)s.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
startsecs = 10
|
||||
stopwaitsecs = 600
|
||||
killasgroup=true
|
||||
priority=998
|
||||
killasgroup = true
|
||||
priority = 998
|
||||
|
||||
{% if gunicorn %}
|
||||
[program:gunicorn]
|
||||
user = allianceserver
|
||||
directory={{ project_directory }}
|
||||
command={{ gunicorn }} {{ project_name }}.wsgi --workers=3 --timeout 120
|
||||
stdout_logfile={{ project_directory }}/log/gunicorn.log
|
||||
stderr_logfile={{ project_directory }}/log/gunicorn.log
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=INT
|
||||
|
||||
directory = {{ project_directory }}
|
||||
command = {{ gunicorn }} {{ project_name }}.wsgi --workers=3 --timeout 120
|
||||
stdout_logfile = {{ project_directory }}/log/%(program_name)s.log
|
||||
stderr_logfile = {{ project_directory }}/log/%(program_name)s.log
|
||||
autostart = true
|
||||
autorestart = true
|
||||
stopsignal = INT
|
||||
{% endif %}
|
||||
|
||||
[eventlistener:memmon]
|
||||
command={{ memmon }} -p worker_00=256MB -p gunicorn=256MB
|
||||
directory={{ project_directory }}
|
||||
events=TICK_60
|
||||
stdout_logfile={{ project_directory }}/log/memmon.log
|
||||
stderr_logfile={{ project_directory }}/log/memmon.log
|
||||
command = {{ memmon }} -p worker_00=256MB -p gunicorn=256MB
|
||||
directory = {{ project_directory }}
|
||||
events = TICK_60
|
||||
stdout_logfile = {{ project_directory }}/log/memmon.log
|
||||
stderr_logfile = {{ project_directory }}/log/memmon.log
|
||||
|
||||
[group:{{ project_name }}]
|
||||
programs=beat,worker{% if gunicorn %},gunicorn{% endif %}
|
||||
priority=999
|
||||
programs = beat,worker{% if gunicorn %},gunicorn{% endif %}
|
||||
priority = 999
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
from string import Formatter
|
||||
from django.urls import include, re_path
|
||||
from typing import Iterable, Optional
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import include, re_path
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from allianceauth.hooks import get_hooks
|
||||
from allianceauth.menu.hooks import MenuItemHook
|
||||
from django.conf import settings
|
||||
|
||||
@@ -37,6 +37,7 @@ import random
|
||||
|
||||
from django.contrib.auth.models import User, Group
|
||||
|
||||
from allianceauth.services.modules.discord.models import DiscordUser
|
||||
from allianceauth.utils.cache import get_redis_client
|
||||
|
||||
logger = logging.getLogger('allianceauth')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import requests
|
||||
import re
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect
|
||||
from django.shortcuts import render, redirect
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .manager import DiscourseManager
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from allianceauth.services.hooks import NameFormatter
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{% endblock page_title %}
|
||||
|
||||
{% block header_nav_brand %}
|
||||
<a class="navbar-brand">{% trans "Mumble History" %} - {{ mumble_url }}</a>
|
||||
{% trans "Mumble History" %} - {{ mumble_url }}
|
||||
{% endblock header_nav_brand %}
|
||||
|
||||
{% block header_nav_collapse_left %}
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
const MUMBLESTATS_DATETIME_FORMAT = 'YYYY-MM-DD, HH:mm';
|
||||
const MUMBLESTATS_DATETIME_FORMAT = 'LLL';
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -104,15 +104,33 @@
|
||||
{ data: 'version' },
|
||||
{
|
||||
data: 'last_connect',
|
||||
render: (data) => {
|
||||
return moment(data).utc().format(MUMBLESTATS_DATETIME_FORMAT);
|
||||
render: {
|
||||
_: (data) => {
|
||||
return data === null
|
||||
? ''
|
||||
: moment(data)
|
||||
.utc()
|
||||
.format(MUMBLESTATS_DATETIME_FORMAT);
|
||||
},
|
||||
sort: (data) => {
|
||||
return data === null ? '' : data;
|
||||
}
|
||||
},
|
||||
className: 'text-end',
|
||||
},
|
||||
{
|
||||
data: 'last_disconnect',
|
||||
render: (data) => {
|
||||
return moment(data).utc().format(MUMBLESTATS_DATETIME_FORMAT);
|
||||
render: {
|
||||
_: (data) => {
|
||||
return data === null
|
||||
? ''
|
||||
: moment(data)
|
||||
.utc()
|
||||
.format(MUMBLESTATS_DATETIME_FORMAT);
|
||||
},
|
||||
sort: (data) => {
|
||||
return data === null ? '' : data;
|
||||
}
|
||||
},
|
||||
className: 'text-end',
|
||||
},
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if request.user.is_superuser %}
|
||||
<a class="btn btn-primary" type="button" id="btnMumbleConnectionHistory" href="{% url 'mumble:connection_history' %}" title="{% translate 'Mumble Connection History' %}">
|
||||
<i class="fa-solid fa-clock-rotate-left"></i> History
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.mumble.view_connection_history %}
|
||||
<a class="btn btn-primary" type="button" id="btnMumbleConnectionHistory" href="{% url 'mumble:connection_history' %}" title="{% translate 'Mumble Connection History' %}">
|
||||
<i class="fa-solid fa-clock-rotate-left"></i> History
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -172,7 +172,7 @@ ul.list-group.list-group-horizontal > li.list-group-item {
|
||||
}
|
||||
}
|
||||
|
||||
/* eve time in navbar
|
||||
/* EVE time in navbar
|
||||
------------------------------------------------------------------------------------- */
|
||||
@media all {
|
||||
.nav-item-eve-time .eve-time-wrapper {
|
||||
|
||||
@@ -14,7 +14,7 @@ $(document).ready(() => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Start the Eve time clock in the top menu bar
|
||||
* Start the EVE time clock in the top menu bar
|
||||
*/
|
||||
setInterval(() => {
|
||||
renderClock($('.eve-time-wrapper .eve-time-clock'));
|
||||
|
||||
@@ -28,7 +28,7 @@ const getDurationString = (duration) => { // eslint-disable-line no-unused-vars
|
||||
};
|
||||
|
||||
/**
|
||||
* returns the current eve time as a formatted string
|
||||
* returns the current EVE time as a formatted string
|
||||
*
|
||||
* condition:
|
||||
* only if moment.js is loaded before,
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
<!-- End Required meta tags -->
|
||||
|
||||
<!-- Meta tags -->
|
||||
<!-- TODO Bundle all the site specific stuff up into its own template for easy override -->
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
{% include 'allianceauth/opengraph.html' %}
|
||||
{% include 'allianceauth/icons.html' %}
|
||||
<!-- Meta tags -->
|
||||
|
||||
<title>{% block title %}{% block page_title %}{% endblock page_title %} - {{ SITE_NAME }}{% endblock title %}</title>
|
||||
|
||||
{% theme_css %}
|
||||
@@ -30,7 +29,8 @@
|
||||
}
|
||||
|
||||
.nav-padding {
|
||||
padding-top: {% header_padding_size %} !important;
|
||||
margin-top: {% header_padding_size %} !important;
|
||||
max-height: calc(100vh - {% header_padding_size %}) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
8
allianceauth/templates/allianceauth/opengraph.html
Normal file
8
allianceauth/templates/allianceauth/opengraph.html
Normal file
@@ -0,0 +1,8 @@
|
||||
{% load static %}
|
||||
|
||||
<meta property="og:title" content="{{ SITE_NAME }}">
|
||||
<meta property="og:image" content="{{ SITE_URL }}{% static 'allianceauth/icons/apple-touch-icon.png' %}">
|
||||
<meta property="og:description" content="Alliance Auth - An auth system for EVE Online to help in-game organizations manage online service access.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="{{ request.META.HTTP_HOST }}">
|
||||
<meta property="og:url" content="{{ request.path }}">
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="collapse navbar-collapse auth-menus-collapse">
|
||||
<ul class="nav navbar-nav navbar-right navbar-pills">
|
||||
<li class="nav-item-eve-time">
|
||||
<div class="eve-time-wrapper">{% translate "Eve Time" %}: <span class="eve-time-clock"></span></div>
|
||||
<div class="eve-time-wrapper">{% translate "EVE time" %}: <span class="eve-time-clock"></span></div>
|
||||
</li>
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{% load static %}
|
||||
|
||||
<img src="{% static 'allianceauth/images/auth-logo.svg' %}" width="{{ logo_width|default:"128px" }}" height="{% if logo_height %}{{ logo_ }}{% else %}{{ logo_width|default:"128px" }}{% endif %}" alt="{{ SITE_NAME }}">
|
||||
<img src="{% static 'allianceauth/images/auth-logo.svg' %}" width="{{ logo_width|default:"128px" }}" height="{% if logo_height %}{{ logo_height }}{% else %}{{ logo_width|default:"128px" }}{% endif %}" alt="{{ SITE_NAME }}">
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import User, Group, Permission
|
||||
from django.test import TestCase
|
||||
|
||||
from allianceauth.eveonline.models import (
|
||||
EveCorporationInfo, EveAllianceInfo, EveCharacter
|
||||
)
|
||||
|
||||
from .auth_utils import AuthUtils
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class TimerForm(forms.ModelForm):
|
||||
future_time = datetime.timedelta(days=days_left, hours=hours_left, minutes=minutes_left)
|
||||
current_time = timezone.now()
|
||||
eve_time = current_time + future_time
|
||||
logger.debug(f"Determined timer eve time is {eve_time} - current time {current_time}, adding {future_time}")
|
||||
logger.debug(f"Determined timer EVE time is {eve_time} - current time {current_time}, adding {future_time}")
|
||||
elif absolute_time:
|
||||
# Use absolute time
|
||||
eve_time = absolute_time
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<th class="text-center">{% translate "Timer" %}</th>
|
||||
<th class="text-center">{% translate "Type" %}</th>
|
||||
<th class="text-center">{% translate "System" %}</th>
|
||||
<th class="text-center">{% translate "EVE Time" %}</th>
|
||||
<th class="text-center">{% translate "EVE time" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<th class="text-center">{% translate "Objective" %}</th>
|
||||
<th class="text-center">{% translate "System" %}</th>
|
||||
<th class="text-center">{% translate "Structure" %}</th>
|
||||
<th class="text-center">{% translate "Eve Time" %}</th>
|
||||
<th class="text-center">{% translate "EVE time" %}</th>
|
||||
<th class="text-center">{% translate "Local Time" %}</th>
|
||||
<th class="text-center">{% translate "Creator" %}</th>
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<div class="allianceauth-timerboard">
|
||||
<div class="col-lg-12 text-center mb-3">
|
||||
<div class="badge bg-primary text-start">
|
||||
<span>{% translate "Current Eve Time:" %}</span>
|
||||
<span>{% translate "Current EVE time:" %}</span>
|
||||
<span id="current-time"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import List, Iterable, Callable
|
||||
|
||||
from django.urls import include
|
||||
import esi.urls
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
PROTOCOL=https://
|
||||
AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN%
|
||||
DOMAIN=%DOMAIN%
|
||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.6.2a
|
||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.6.4
|
||||
|
||||
# Nginx Proxy Manager
|
||||
PROXY_HTTP_PORT=80
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
FROM python:3.11-slim
|
||||
ARG AUTH_VERSION=v4.6.2a
|
||||
ARG AUTH_VERSION=v4.6.4
|
||||
ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION}
|
||||
ENV AUTH_USER=allianceauth
|
||||
ENV AUTH_GROUP=allianceauth
|
||||
|
||||
@@ -81,7 +81,7 @@ Example implementation for a celery chain:
|
||||
|
||||
```python
|
||||
from allianceauth.services.hooks import get_extension_logger
|
||||
from celery import shared_task, chain
|
||||
from celery import shared_task, group
|
||||
|
||||
logger = get_extension_logger(__name__)
|
||||
|
||||
@@ -98,18 +98,23 @@ def long_runner():
|
||||
task_signature = example.si()
|
||||
my_tasks.append(task_signature)
|
||||
|
||||
chain(my_tasks).delay()
|
||||
group(my_tasks).delay()
|
||||
```
|
||||
|
||||
In this example, we first add 10 example tasks that need to run one after the other to a list. This can be done by creating a so-called signature for a task. Those signatures are a kind of wrapper for tasks and can be used in various ways to compose work flow for tasks.
|
||||
|
||||
The list of task signatures is then converted to a chain and started asynchronously.
|
||||
|
||||
:::{note}
|
||||
In this example we import group to execute all tasks independently.
|
||||
If you wish to run them in order (and stop if a tasks fail) you can use `celery.chain` instead of `celery.group`
|
||||
|
||||
For more information on signature and work flows see the official documentation on [Canvas](https://docs.celeryproject.org/en/latest/userguide/canvas.html).
|
||||
:::
|
||||
|
||||
:::{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.
|
||||
|
||||
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.
|
||||
:::
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ dependencies = [
|
||||
"requests>=2.9.1",
|
||||
"requests-oauthlib",
|
||||
"semantic-version",
|
||||
"slixmpp",
|
||||
"slixmpp<1.9",
|
||||
]
|
||||
optional-dependencies.docs = [
|
||||
"myst-parser",
|
||||
|
||||
@@ -47,6 +47,7 @@ CACHES = {
|
||||
ESI_SSO_CLIENT_ID = "dummy"
|
||||
ESI_SSO_CLIENT_SECRET = "dummy"
|
||||
ESI_SSO_CALLBACK_URL = f"{SITE_URL}/sso/callback"
|
||||
ESI_USER_CONTACT_EMAIL = "dummy@example.net"
|
||||
|
||||
########################
|
||||
# XenForo Configuration
|
||||
|
||||
@@ -37,3 +37,4 @@ ALLIANCEAUTH_DASHBOARD_TASK_STATISTICS_DISABLED = True # disable for tests
|
||||
ESI_SSO_CLIENT_ID = "dummy"
|
||||
ESI_SSO_CLIENT_SECRET = "dummy"
|
||||
ESI_SSO_CALLBACK_URL = f"{SITE_URL}/sso/callback"
|
||||
ESI_USER_CONTACT_EMAIL = "dummy@example.net"
|
||||
|
||||
Reference in New Issue
Block a user