mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-11 09:36:24 +01:00
Compare commits
45 Commits
v4.1.0
...
cbe6c821cc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbe6c821cc | ||
|
|
de9d2b39a6 | ||
|
|
0d5f22288b | ||
|
|
e0d76dc268 | ||
|
|
ecc9e68330 | ||
|
|
710149ec21 | ||
|
|
3c2c137dad | ||
|
|
a8271c4189 | ||
|
|
3315ae7778 | ||
|
|
d2f048f8fe | ||
|
|
0fe2855faa | ||
|
|
79a1fa3d7c | ||
|
|
96fe88d5c7 | ||
|
|
59391ad3c5 | ||
|
|
94e9c08422 | ||
|
|
acff3695bc | ||
|
|
43ec8514aa | ||
|
|
4c629b193f | ||
|
|
c651da4011 | ||
|
|
da382cffd1 | ||
|
|
4ecfc3afd8 | ||
|
|
4eb7dbbe62 | ||
|
|
c96ba65296 | ||
|
|
ff2f60f7f3 | ||
|
|
3000545c98 | ||
|
|
f3ad092ef2 | ||
|
|
a012e7df2f | ||
|
|
1fa77412c0 | ||
|
|
e56caeb22b | ||
|
|
ceb07ebc67 | ||
|
|
237075d45c | ||
|
|
7099b1946d | ||
|
|
e416ab8ff2 | ||
|
|
2802ed03a5 | ||
|
|
4af73c76fe | ||
|
|
b6149979aa | ||
|
|
cb20288427 | ||
|
|
db6f4c91dc | ||
|
|
57ac7a5277 | ||
|
|
136438f9c2 | ||
|
|
e2be8b3440 | ||
|
|
04f3473ef3 | ||
|
|
255cb0da8d | ||
|
|
069352fb0f | ||
|
|
66e8ddb684 |
@@ -25,7 +25,7 @@ before_script:
|
||||
pre-commit-check:
|
||||
<<: *only-default
|
||||
stage: pre-commit
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
# variables:
|
||||
# PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
|
||||
# cache:
|
||||
@@ -53,7 +53,7 @@ secret_detection:
|
||||
|
||||
test-3.8-core:
|
||||
<<: *only-default
|
||||
image: python:3.8-bullseye
|
||||
image: python:3.8-bookworm
|
||||
script:
|
||||
- tox -e py38-core
|
||||
artifacts:
|
||||
@@ -65,7 +65,7 @@ test-3.8-core:
|
||||
|
||||
test-3.9-core:
|
||||
<<: *only-default
|
||||
image: python:3.9-bullseye
|
||||
image: python:3.9-bookworm
|
||||
script:
|
||||
- tox -e py39-core
|
||||
artifacts:
|
||||
@@ -77,7 +77,7 @@ test-3.9-core:
|
||||
|
||||
test-3.10-core:
|
||||
<<: *only-default
|
||||
image: python:3.10-bullseye
|
||||
image: python:3.10-bookworm
|
||||
script:
|
||||
- tox -e py310-core
|
||||
artifacts:
|
||||
@@ -89,7 +89,7 @@ test-3.10-core:
|
||||
|
||||
test-3.11-core:
|
||||
<<: *only-default
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
script:
|
||||
- tox -e py311-core
|
||||
artifacts:
|
||||
@@ -101,7 +101,7 @@ test-3.11-core:
|
||||
|
||||
test-3.12-core:
|
||||
<<: *only-default
|
||||
image: python:3.12-rc-bullseye
|
||||
image: python:3.12-bookworm
|
||||
script:
|
||||
- tox -e py312-core
|
||||
artifacts:
|
||||
@@ -113,7 +113,7 @@ test-3.12-core:
|
||||
|
||||
test-3.8-all:
|
||||
<<: *only-default
|
||||
image: python:3.8-bullseye
|
||||
image: python:3.8-bookworm
|
||||
script:
|
||||
- tox -e py38-all
|
||||
artifacts:
|
||||
@@ -125,7 +125,7 @@ test-3.8-all:
|
||||
|
||||
test-3.9-all:
|
||||
<<: *only-default
|
||||
image: python:3.9-bullseye
|
||||
image: python:3.9-bookworm
|
||||
script:
|
||||
- tox -e py39-all
|
||||
artifacts:
|
||||
@@ -137,7 +137,7 @@ test-3.9-all:
|
||||
|
||||
test-3.10-all:
|
||||
<<: *only-default
|
||||
image: python:3.10-bullseye
|
||||
image: python:3.10-bookworm
|
||||
script:
|
||||
- tox -e py310-all
|
||||
artifacts:
|
||||
@@ -149,7 +149,7 @@ test-3.10-all:
|
||||
|
||||
test-3.11-all:
|
||||
<<: *only-default
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
script:
|
||||
- tox -e py311-all
|
||||
artifacts:
|
||||
@@ -162,7 +162,7 @@ test-3.11-all:
|
||||
|
||||
test-3.12-all:
|
||||
<<: *only-default
|
||||
image: python:3.12-rc-bullseye
|
||||
image: python:3.12-bookworm
|
||||
script:
|
||||
- tox -e py312-all
|
||||
artifacts:
|
||||
@@ -174,7 +174,7 @@ test-3.12-all:
|
||||
|
||||
build-test:
|
||||
stage: test
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
|
||||
before_script:
|
||||
- python -m pip install --upgrade pip
|
||||
@@ -193,13 +193,13 @@ build-test:
|
||||
|
||||
test-docs:
|
||||
<<: *only-default
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
script:
|
||||
- tox -e docs
|
||||
|
||||
deploy_production:
|
||||
stage: deploy
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
|
||||
before_script:
|
||||
- python -m pip install --upgrade pip
|
||||
|
||||
@@ -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.1.0'
|
||||
__version__ = '4.2.2'
|
||||
__title__ = 'Alliance Auth'
|
||||
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
||||
NAME = f'{__title__} v{__version__}'
|
||||
|
||||
@@ -101,11 +101,38 @@ def analytics_daily_stats():
|
||||
event_type='Stats')
|
||||
|
||||
for appconfig in apps.get_app_configs():
|
||||
analytics_event(namespace='allianceauth.analytics',
|
||||
task='send_extension_stats',
|
||||
label=appconfig.label,
|
||||
value=1,
|
||||
event_type='Stats')
|
||||
if appconfig.label in [
|
||||
"django_celery_beat",
|
||||
"bootstrapform",
|
||||
"messages",
|
||||
"sessions",
|
||||
"auth",
|
||||
"staticfiles",
|
||||
"users",
|
||||
"addons",
|
||||
"admin",
|
||||
"humanize",
|
||||
"contenttypes",
|
||||
"sortedm2m",
|
||||
"django_bootstrap5",
|
||||
"tokens",
|
||||
"authentication",
|
||||
"services",
|
||||
"framework",
|
||||
"notifications"
|
||||
"eveonline",
|
||||
"navhelper",
|
||||
"analytics",
|
||||
"menu",
|
||||
"theme"
|
||||
]:
|
||||
pass
|
||||
else:
|
||||
analytics_event(namespace='allianceauth.analytics',
|
||||
task='send_extension_stats',
|
||||
label=appconfig.label,
|
||||
value=1,
|
||||
event_type='Stats')
|
||||
|
||||
|
||||
@shared_task()
|
||||
|
||||
@@ -5,26 +5,5 @@ from django.core.checks import Warning, Error, register
|
||||
class AllianceAuthConfig(AppConfig):
|
||||
name = 'allianceauth'
|
||||
|
||||
|
||||
@register()
|
||||
def check_settings(app_configs, **kwargs):
|
||||
from django.conf import settings
|
||||
|
||||
errors = []
|
||||
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."))
|
||||
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."))
|
||||
if hasattr(settings, "CSRF_TRUSTED_ORIGINS"):
|
||||
if 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."))
|
||||
else:
|
||||
errors.append(Error(
|
||||
"No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified"))
|
||||
|
||||
return errors
|
||||
def ready(self) -> None:
|
||||
import allianceauth.checks # noqa
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{% translate "Dashboard" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-around align-self-center flex-wrap">
|
||||
<div class="row">
|
||||
{% for dash in views %}
|
||||
{{ dash | safe }}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% load i18n %}
|
||||
<div id="aa-dashboard-panel-characters" class="col-12 col-xl-8 align-self-stretch p-2 ps-0 pe-0 ps-xl-0 pe-xl-2">
|
||||
<div id="aa-dashboard-panel-characters" class="col-12 col-xl-8 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
{% translate "Characters" as widget_title %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% load i18n %}
|
||||
<div id="aa-dashboard-panel-membership" class="col-12 col-xl-4 align-self-stretch py-2 ps-xl-2">
|
||||
<div id="aa-dashboard-panel-membership" class="col-12 col-xl-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
{% translate "Membership" as widget_title %}
|
||||
|
||||
187
allianceauth/checks.py
Normal file
187
allianceauth/checks.py
Normal file
@@ -0,0 +1,187 @@
|
||||
from typing import List
|
||||
from django import db
|
||||
from django.core.checks import CheckMessage, Error, register, Warning
|
||||
from allianceauth.utils.cache import get_redis_client
|
||||
from django.utils import timezone
|
||||
from packaging.version import InvalidVersion, Version as Pep440Version
|
||||
from celery import current_app
|
||||
from django.conf import settings
|
||||
from sqlite3.dbapi2 import sqlite_version_info
|
||||
|
||||
"""
|
||||
A = System Packages
|
||||
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"))
|
||||
|
||||
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"))
|
||||
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"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_redis(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
try:
|
||||
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="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", 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="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", 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="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A018"))
|
||||
elif redis_version.major in [6, 5]:
|
||||
errors.append(Error(f"Redis {redis_version.public} EOL", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A003"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: 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))
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm MySQL Version"))
|
||||
return errors
|
||||
|
||||
# MySQL 8
|
||||
if mysql_version.major == 8 and 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="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A004"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 3:
|
||||
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A005"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 2:
|
||||
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A006"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 1:
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A007"))
|
||||
elif mysql_version.major == 8 and 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="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A008"))
|
||||
elif mysql_version.major < 8: # This will also catch Mariadb 5.x
|
||||
errors.append(Error(f"MySQL or MariaDB {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A009"))
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql": # Still to find a way to determine MySQL vs MariaDB
|
||||
try:
|
||||
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 and 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="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A010"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor == 2:
|
||||
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", 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="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A011"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor == 1:
|
||||
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", 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="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A012"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor in [0, 3]: # Demote versions down here once EOL
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A013"))
|
||||
|
||||
# MariaDB 10
|
||||
elif mariadb_version.major == 10 and 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="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A014"))
|
||||
elif mariadb_version.major == 10 and 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="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A0015"))
|
||||
elif mariadb_version.major == 10 and 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="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A016"))
|
||||
elif mariadb_version.major == 10 and 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="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A017"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_sqlite(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
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))
|
||||
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"))
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
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"))
|
||||
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"))
|
||||
|
||||
# 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"))
|
||||
# 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"))
|
||||
|
||||
# if connection.vendor == "sqlite":
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def celery_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
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"))
|
||||
except KeyError:
|
||||
errors.append(Error("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"))
|
||||
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"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
# IDEAS
|
||||
|
||||
# Any other celery things weve manually changed over the years
|
||||
# I'd be happy to add Community App checks, old versions the owners dont want to support etc.
|
||||
|
||||
|
||||
# Check Default Collation on DB
|
||||
# Check Charset Collation on all tables
|
||||
3
allianceauth/custom_css/__init__.py
Normal file
3
allianceauth/custom_css/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Initializes the custom_css module.
|
||||
"""
|
||||
25
allianceauth/custom_css/admin.py
Normal file
25
allianceauth/custom_css/admin.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
Admin classes for custom_css app
|
||||
"""
|
||||
|
||||
# Django
|
||||
from django.contrib import admin
|
||||
|
||||
# Django Solos
|
||||
from solo.admin import SingletonModelAdmin
|
||||
|
||||
# Alliance Auth Custom CSS
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
from allianceauth.custom_css.forms import CustomCSSAdminForm
|
||||
|
||||
|
||||
@admin.register(CustomCSS)
|
||||
class CustomCSSAdmin(SingletonModelAdmin):
|
||||
"""
|
||||
Custom CSS Admin
|
||||
"""
|
||||
|
||||
form = CustomCSSAdminForm
|
||||
|
||||
# Leave this here for when we decide to add syntax highlighting to the CSS editor
|
||||
# change_form_template = 'custom_css/admin/change_form.html'
|
||||
13
allianceauth/custom_css/apps.py
Normal file
13
allianceauth/custom_css/apps.py
Normal file
@@ -0,0 +1,13 @@
|
||||
"""
|
||||
Django app configuration for custom_css
|
||||
"""
|
||||
|
||||
# Django
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class CustomCSSConfig(AppConfig):
|
||||
name = "allianceauth.custom_css"
|
||||
label = "custom_css"
|
||||
verbose_name = _("Custom CSS")
|
||||
29
allianceauth/custom_css/forms.py
Normal file
29
allianceauth/custom_css/forms.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Forms for custom_css app
|
||||
"""
|
||||
|
||||
# Alliance Auth Custom CSS
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
from allianceauth.custom_css.widgets import CssEditorWidget
|
||||
|
||||
# Django
|
||||
from django import forms
|
||||
|
||||
|
||||
class CustomCSSAdminForm(forms.ModelForm):
|
||||
"""
|
||||
Form for editing custom CSS
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = CustomCSS
|
||||
fields = ("css",)
|
||||
widgets = {
|
||||
"css": CssEditorWidget(
|
||||
attrs={
|
||||
"style": "width: 90%; height: 100%;",
|
||||
"data-editor": "code-highlight",
|
||||
"data-language": "css",
|
||||
}
|
||||
)
|
||||
}
|
||||
42
allianceauth/custom_css/migrations/0001_initial.py
Normal file
42
allianceauth/custom_css/migrations/0001_initial.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# Generated by Django 4.2.15 on 2024-08-14 11:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="CustomCSS",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"css",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="This CSS will be added to the site after the default CSS.",
|
||||
null=True,
|
||||
verbose_name="Your custom CSS",
|
||||
),
|
||||
),
|
||||
("timestamp", models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Custom CSS",
|
||||
"verbose_name_plural": "Custom CSS",
|
||||
"default_permissions": (),
|
||||
},
|
||||
),
|
||||
]
|
||||
0
allianceauth/custom_css/migrations/__init__.py
Normal file
0
allianceauth/custom_css/migrations/__init__.py
Normal file
143
allianceauth/custom_css/models.py
Normal file
143
allianceauth/custom_css/models.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""
|
||||
Models for the custom_css app
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
# Django Solo
|
||||
from solo.models import SingletonModel
|
||||
|
||||
# Django
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class CustomCSS(SingletonModel):
|
||||
"""
|
||||
Model for storing custom CSS for the site
|
||||
"""
|
||||
|
||||
css = models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_("Your custom CSS"),
|
||||
help_text=_("This CSS will be added to the site after the default CSS."),
|
||||
)
|
||||
timestamp = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Meta for CustomCSS
|
||||
"""
|
||||
|
||||
default_permissions = ()
|
||||
verbose_name = _("Custom CSS")
|
||||
verbose_name_plural = _("Custom CSS")
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
String representation of CustomCSS
|
||||
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
return str(_("Custom CSS"))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
Save method for CustomCSS
|
||||
|
||||
:param args:
|
||||
:type args:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
self.pk = 1
|
||||
|
||||
if self.css and len(self.css.replace(" ", "")) > 0:
|
||||
# Write the custom CSS to a file
|
||||
custom_css_file = open(
|
||||
f"{settings.STATIC_ROOT}allianceauth/custom-styles.css", "w+"
|
||||
)
|
||||
custom_css_file.write(self.compress_css())
|
||||
custom_css_file.close()
|
||||
else:
|
||||
# Remove the custom CSS file
|
||||
try:
|
||||
os.remove(f"{settings.STATIC_ROOT}allianceauth/custom-styles.css")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def compress_css(self) -> str:
|
||||
"""
|
||||
Compress CSS
|
||||
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
css = self.css
|
||||
new_css = ""
|
||||
|
||||
# Remove comments
|
||||
css = re.sub(pattern=r"\s*/\*\s*\*/", repl="$$HACK1$$", string=css)
|
||||
css = re.sub(pattern=r"/\*[\s\S]*?\*/", repl="", string=css)
|
||||
css = css.replace("$$HACK1$$", "/**/")
|
||||
|
||||
# url() doesn't need quotes
|
||||
css = re.sub(pattern=r'url\((["\'])([^)]*)\1\)', repl=r"url(\2)", string=css)
|
||||
|
||||
# Spaces may be safely collapsed as generated content will collapse them anyway.
|
||||
css = re.sub(pattern=r"\s+", repl=" ", string=css)
|
||||
|
||||
# Shorten collapsable colors: #aabbcc to #abc
|
||||
css = re.sub(
|
||||
pattern=r"#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)",
|
||||
repl=r"#\1\2\3\4",
|
||||
string=css,
|
||||
)
|
||||
|
||||
# Fragment values can loose zeros
|
||||
css = re.sub(
|
||||
pattern=r":\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;", repl=r":\1;", string=css
|
||||
)
|
||||
|
||||
for rule in re.findall(pattern=r"([^{]+){([^}]*)}", string=css):
|
||||
# We don't need spaces around operators
|
||||
selectors = [
|
||||
re.sub(
|
||||
pattern=r"(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])",
|
||||
repl=r"",
|
||||
string=selector.strip(),
|
||||
)
|
||||
for selector in rule[0].split(",")
|
||||
]
|
||||
|
||||
# Order is important, but we still want to discard repetitions
|
||||
properties = {}
|
||||
porder = []
|
||||
|
||||
for prop in re.findall(pattern="(.*?):(.*?)(;|$)", string=rule[1]):
|
||||
key = prop[0].strip().lower()
|
||||
|
||||
if key not in porder:
|
||||
porder.append(key)
|
||||
|
||||
properties[key] = prop[1].strip()
|
||||
|
||||
# output rule if it contains any declarations
|
||||
if properties:
|
||||
new_css += "{}{{{}}}".format(
|
||||
",".join(selectors),
|
||||
"".join([f"{key}:{properties[key]};" for key in porder])[:-1],
|
||||
)
|
||||
|
||||
return new_css
|
||||
@@ -0,0 +1,48 @@
|
||||
{% extends "admin/change_form.html" %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
<fieldset class="module aligned {{ fieldset.classes }}">
|
||||
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
|
||||
|
||||
{% if fieldset.description %}
|
||||
<div class="description">{{ fieldset.description|safe }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% for line in fieldset %}
|
||||
<div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
|
||||
{% if line.fields|length == 1 %}{{ line.errors }}{% else %}<div class="flex-container form-multiline">{% endif %}
|
||||
|
||||
{% for field in line %}
|
||||
<div>
|
||||
{% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
|
||||
|
||||
<div class="flex-container{% if not line.fields|length == 1 %} fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}{% elif field.is_checkbox %} checkbox-row{% endif %}">
|
||||
{% if field.is_checkbox %}
|
||||
{{ field.field }}{{ field.label_tag }}
|
||||
{% else %}
|
||||
{{ field.label_tag }}
|
||||
{% if field.is_readonly %}
|
||||
<div class="readonly">{{ field.contents }}</div>
|
||||
{% else %}
|
||||
{{ field.field }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if field.field.help_text %}
|
||||
<div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}>
|
||||
<div>{{ field.field.help_text|safe }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if not line.fields|length == 1 %}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% load custom_css %}
|
||||
|
||||
{% custom_css_static 'allianceauth/custom-styles.css' %}
|
||||
3
allianceauth/custom_css/templatetags/__init__.py
Normal file
3
allianceauth/custom_css/templatetags/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Init file for custom_css templatetags
|
||||
"""
|
||||
48
allianceauth/custom_css/templatetags/custom_css.py
Normal file
48
allianceauth/custom_css/templatetags/custom_css.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
Custom template tags for custom_css app
|
||||
"""
|
||||
|
||||
# Alliance Auth Custom CSS
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
|
||||
# Django
|
||||
from django.conf import settings
|
||||
from django.template.defaulttags import register
|
||||
from django.templatetags.static import static
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def custom_css_static(path: str) -> str:
|
||||
"""
|
||||
Versioned static URL
|
||||
This is to make sure to break the browser cache on CSS updates.
|
||||
|
||||
Example: /static/allianceauth/custom-styles.css?v=1234567890
|
||||
|
||||
:param path:
|
||||
:type path:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
try:
|
||||
Path(f"{settings.STATIC_ROOT}{path}").resolve(strict=True)
|
||||
except FileNotFoundError:
|
||||
return ""
|
||||
else:
|
||||
try:
|
||||
custom_css = CustomCSS.objects.get(pk=1)
|
||||
except CustomCSS.DoesNotExist:
|
||||
return ""
|
||||
else:
|
||||
custom_css_changed = custom_css.timestamp.timestamp()
|
||||
custom_css_version = (
|
||||
str(custom_css_changed).replace(" ", "").replace(":", "").replace("-", "")
|
||||
) # remove spaces, colons, and dashes
|
||||
static_url = static(path)
|
||||
versioned_url = static_url + "?v=" + custom_css_version
|
||||
|
||||
return mark_safe(f'<link rel="stylesheet" href="{versioned_url}">')
|
||||
38
allianceauth/custom_css/widgets.py
Normal file
38
allianceauth/custom_css/widgets.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Form widgets for custom_css app
|
||||
"""
|
||||
|
||||
# Django
|
||||
from django import forms
|
||||
|
||||
# Alliance Auth
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
|
||||
|
||||
class CssEditorWidget(forms.Textarea):
|
||||
"""
|
||||
Widget for editing CSS
|
||||
"""
|
||||
|
||||
def __init__(self, attrs=None):
|
||||
default_attrs = {"class": "custom-css-editor"}
|
||||
|
||||
if attrs:
|
||||
default_attrs.update(attrs)
|
||||
|
||||
super().__init__(default_attrs)
|
||||
|
||||
# For when we want to add some sort of syntax highlight to it, which is not that
|
||||
# easy to do on a textarea field though.
|
||||
# `highlight.js` is just used as an example here, and doesn't work on a textarea field.
|
||||
# class Media:
|
||||
# css = {
|
||||
# "all": (
|
||||
# "/static/custom_css/libs/highlight.js/11.10.0/styles/github.min.css",
|
||||
# )
|
||||
# }
|
||||
# js = (
|
||||
# "/static/custom_css/libs/highlight.js/11.10.0/highlight.min.js",
|
||||
# "/static/custom_css/libs/highlight.js/11.10.0/languages/css.min.js",
|
||||
# "/static/custom_css/javascript/custom-css.min.js",
|
||||
# )
|
||||
@@ -1,7 +1,7 @@
|
||||
{#Usage:#}
|
||||
{# {% include "framework/dashboard/widget-title.html" with title="Foobar" %}#}
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="text-center">
|
||||
<h4 class="ms-auto me-auto mb-3">
|
||||
{{ title }}
|
||||
</h4>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load i18n %}
|
||||
{% load evelinks %}
|
||||
|
||||
<div class="col-12 align-self-stretch py-2">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
{% translate "Upcoming Fleets" as widget_title %}
|
||||
|
||||
@@ -22,6 +22,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.humanize',
|
||||
'django_celery_beat',
|
||||
'solo',
|
||||
'bootstrapform',
|
||||
'django_bootstrap5', # https://github.com/zostera/django-bootstrap5
|
||||
'sortedm2m',
|
||||
@@ -39,6 +40,7 @@ INSTALLED_APPS = [
|
||||
'allianceauth.theme.darkly',
|
||||
'allianceauth.theme.flatly',
|
||||
'allianceauth.theme.materia',
|
||||
"allianceauth.custom_css",
|
||||
]
|
||||
|
||||
SECRET_KEY = "wow I'm a really bad default secret key"
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block url %}
|
||||
<a href="{{ service_url }}">{{ service_url }}</a>
|
||||
{% if username != '' %}
|
||||
<a href="mumble://{{ connect_url }}">{{ service_url }}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block user %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% load i18n %}
|
||||
<div id="esi-alert" class="col-12 align-self-stretch py-2 collapse">
|
||||
<div id="esi-alert" class="col-12 collapse">
|
||||
<div class="alert alert-warning">
|
||||
<p class="text-center ">{% translate 'Your Server received an ESI error response code of ' %}<b id="esi-code">?</b></p>
|
||||
<hr>
|
||||
@@ -23,7 +23,7 @@
|
||||
console.log("ESI Check: ", JSON.stringify(responseJson, null, 2));
|
||||
|
||||
const status = responseJson.status;
|
||||
if (status != 200) {
|
||||
if (status !== 200) {
|
||||
elemCode.textContent = status
|
||||
elemMessage.textContent = responseJson.data.error;
|
||||
new bootstrap.Collapse(elemCard, {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% load humanize %}
|
||||
|
||||
{% if notifications %}
|
||||
<div id="aa-dashboard-panel-admin-notifications" class="col-12 align-self-stretch pb-2">
|
||||
<div id="aa-dashboard-panel-admin-notifications" class="col-12 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% translate "Alliance Auth Notifications" as widget_title %}
|
||||
@@ -13,9 +13,9 @@
|
||||
{% for notif in notifications %}
|
||||
<li class="list-group-item">
|
||||
{% if notif.state == 'opened' %}
|
||||
<span class="badge bg-success">{% translate "Open" %}</span>
|
||||
<span class="badge bg-success me-2">{% translate "Open" %}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% translate "Closed" %}</span>
|
||||
<span class="badge bg-danger me-2">{% translate "Closed" %}</span>
|
||||
{% endif %}
|
||||
<a href="{{ notif.web_url }}" target="_blank">#{{ notif.iid }} {{ notif.title }}</a>
|
||||
</li>
|
||||
@@ -46,7 +46,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-12 align-self-stretch py-2">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-body row">
|
||||
<div id="aa-dashboard-panel-software-version" class="col-xl-6 col-lg-12 col-md-12 col-sm-12">
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
</style>
|
||||
|
||||
{% block extra_css %}{% endblock extra_css %}
|
||||
|
||||
{% include 'custom_css/bundles/custom-css.html' %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
{% extends "allianceauth/base-bs5.html" %}
|
||||
|
||||
{% load theme_tags %}
|
||||
|
||||
{% block page_title %}
|
||||
{{ error_title }}
|
||||
{% endblock page_title %}
|
||||
|
||||
{% block content %}
|
||||
<div>
|
||||
{% include "framework/header/page-header.html" with title=error_title %}
|
||||
<div class="d-flex flex-column" style="height: calc(100vh - {% header_padding_size %}); margin-top: -1rem; margin-bottom: -1rem;">
|
||||
<div class="d-flex flex-grow-1 justify-content-center align-items-center">
|
||||
<div>
|
||||
{% include "framework/header/page-header.html" with title=error_title %}
|
||||
|
||||
<div class="text-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="150"
|
||||
height="150"
|
||||
fill="currentColor"
|
||||
class="bi bi-exclamation-triangle"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path
|
||||
d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"
|
||||
/>
|
||||
<path
|
||||
d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"
|
||||
/>
|
||||
</svg>
|
||||
<div class="text-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="150"
|
||||
height="150"
|
||||
fill="currentColor"
|
||||
class="bi bi-exclamation-triangle"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path
|
||||
d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"
|
||||
/>
|
||||
<path
|
||||
d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<p class="text-center">{{ error_message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center">{{ error_message }}</p>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@@ -27,6 +27,7 @@ class BootstrapThemeHook(ThemeHook):
|
||||
self,
|
||||
"Bootstrap",
|
||||
"Powerful, extensible, and feature-packed frontend toolkit.",
|
||||
html_tags={"data-theme": "bootstrap"},
|
||||
css=CSS_STATICS,
|
||||
js=JS_STATICS,
|
||||
header_padding="3.5em"
|
||||
@@ -44,9 +45,9 @@ class BootstrapDarkThemeHook(ThemeHook):
|
||||
self,
|
||||
"Bootstrap Dark",
|
||||
"Powerful, extensible, and feature-packed frontend toolkit.",
|
||||
html_tags={"data-theme": "bootstrap-dark"},
|
||||
css=CSS_STATICS,
|
||||
js=JS_STATICS,
|
||||
html_tags="data-bs-theme=dark",
|
||||
header_padding="3.5em"
|
||||
)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ class DarklyThemeHook(ThemeHook):
|
||||
self,
|
||||
"Darkly",
|
||||
"Flatly in night mode!",
|
||||
html_tags={"data-theme": "darkly"},
|
||||
css=[{
|
||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/darkly/bootstrap.min.css",
|
||||
"integrity": "sha512-HDszXqSUU0om4Yj5dZOUNmtwXGWDa5ppESlX98yzbBS+z+3HQ8a/7kcdI1dv+jKq+1V5b01eYurE7+yFjw6Rdg=="
|
||||
|
||||
@@ -13,6 +13,7 @@ class FlatlyThemeHook(ThemeHook):
|
||||
self,
|
||||
"Flatly",
|
||||
"Flat and modern!",
|
||||
html_tags={"data-theme": "flatly"},
|
||||
css=[{
|
||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/flatly/bootstrap.min.css",
|
||||
"integrity": "sha512-qoT4KwnRpAQ9uczPsw7GunsNmhRnYwSlE2KRCUPRQHSkDuLulCtDXuC2P/P6oqr3M5hoGagUG9pgHDPkD2zCDA=="
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Union
|
||||
|
||||
|
||||
class ThemeHook:
|
||||
"""
|
||||
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
|
||||
these can be local or CDN delivered
|
||||
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
|
||||
These can be local or CDN delivered.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -14,7 +14,7 @@ class ThemeHook:
|
||||
js: List[dict],
|
||||
css_template: Optional[str] = None,
|
||||
js_template: Optional[str] = None,
|
||||
html_tags: Optional[str] = "",
|
||||
html_tags: Optional[Union[dict, str]] = None,
|
||||
header_padding: Optional[str] = "4em"):
|
||||
"""
|
||||
:param name: Theme python name
|
||||
@@ -29,6 +29,10 @@ class ThemeHook:
|
||||
:type css_template: Optional[str], optional
|
||||
:param js_template: _description_, defaults to None
|
||||
:type js_template: Optional[str], optional
|
||||
:param html_tags: Attributes added to the `<html>` tag, defaults to None
|
||||
:type html_tags: Optional[dict|str], optional
|
||||
:param header_padding: Top padding, defaults to "4em"
|
||||
:type header_padding: Optional[str], optional
|
||||
"""
|
||||
self.name = name
|
||||
self.description = description
|
||||
@@ -41,7 +45,11 @@ class ThemeHook:
|
||||
self.css_template = css_template
|
||||
self.js_template = js_template
|
||||
|
||||
self.html_tags = html_tags
|
||||
self.html_tags = (
|
||||
" ".join([f"{key}={value}" for key, value in html_tags.items()])
|
||||
if isinstance(html_tags, dict)
|
||||
else html_tags
|
||||
)
|
||||
self.header_padding = header_padding
|
||||
def get_name(self):
|
||||
return f"{self.__class__.__module__}.{self.__class__.__name__}"
|
||||
|
||||
@@ -13,6 +13,7 @@ class MateriaThemeHook(ThemeHook):
|
||||
self,
|
||||
"Materia",
|
||||
"Material is the metaphor",
|
||||
html_tags={"data-theme": "materia"},
|
||||
css=[{
|
||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/materia/bootstrap.min.css",
|
||||
"integrity": "sha512-2S9Do+uTmZmmJpdmAcOKdUrK/YslcvAuRfIF2ws8+BW9AvZXMRZM+o8Wq+PZrfISD6ZlIaeCWWZAdeprXIoYuQ=="
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load i18n %}
|
||||
{% load evelinks %}
|
||||
|
||||
<div class="col-12 align-self-stretch py-2">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
{% translate "Upcoming Timers" as widget_title %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
PROTOCOL=https://
|
||||
AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN%
|
||||
DOMAIN=%DOMAIN%
|
||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.1.0
|
||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.2.2
|
||||
|
||||
# Nginx Proxy Manager
|
||||
PROXY_HTTP_PORT=80
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
FROM python:3.11-slim
|
||||
ARG AUTH_VERSION=v4.1.0
|
||||
ARG AUTH_VERSION=v4.2.2
|
||||
ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION}
|
||||
ENV AUTH_USER=allianceauth
|
||||
ENV AUTH_GROUP=allianceauth
|
||||
@@ -9,21 +9,21 @@ ENV AUTH_HOME=/home/allianceauth
|
||||
|
||||
# Setup user and directory permissions
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
RUN groupadd -g 61000 ${AUTH_GROUP}
|
||||
RUN useradd -g 61000 -l -M -s /bin/false -u 61000 ${AUTH_USER}
|
||||
RUN mkdir -p ${STATIC_BASE} \
|
||||
&& chown ${AUTH_USERGROUP} ${STATIC_BASE} \
|
||||
&& mkdir -p ${AUTH_HOME} \
|
||||
&& chown ${AUTH_USERGROUP} ${AUTH_HOME}
|
||||
RUN groupadd -g 61000 ${AUTH_GROUP} && \
|
||||
useradd -g 61000 -l -m -s /bin/false -u 61000 ${AUTH_USER}
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
|
||||
libmariadb-dev gcc git pkg-config
|
||||
RUN mkdir -p ${STATIC_BASE}/myauth/static \
|
||||
&& chown ${AUTH_USERGROUP} ${STATIC_BASE}/myauth/static
|
||||
|
||||
# Install python dependencies
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install wheel gunicorn
|
||||
RUN pip install ${AUTH_PACKAGE}
|
||||
# Install Build Dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends libmariadb-dev gcc git pkg-config \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install AA and Dependencies
|
||||
RUN pip install --no-cache-dir ${AUTH_PACKAGE} gunicorn
|
||||
|
||||
# Switch to non-root user
|
||||
USER ${AUTH_USER}
|
||||
@@ -33,7 +33,6 @@ WORKDIR ${AUTH_HOME}
|
||||
RUN allianceauth start myauth
|
||||
COPY /allianceauth/project_template/project_name/settings/local.py ${AUTH_HOME}/myauth/myauth/settings/local.py
|
||||
RUN allianceauth update myauth
|
||||
RUN mkdir -p ${STATIC_BASE}/myauth/static
|
||||
|
||||
RUN echo 'alias auth="python $AUTH_HOME/myauth/manage.py"' >> ~/.bashrc && \
|
||||
source ~/.bashrc
|
||||
|
||||
@@ -9,6 +9,10 @@ from django.conf import settings # noqa
|
||||
|
||||
app = Celery('myauth')
|
||||
|
||||
# Automatically try to establish the connection to the AMQP broker on
|
||||
# Celery startup if it is unavailable.
|
||||
app.conf.broker_connection_retry_on_startup = 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')
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
ARG AA_DOCKER_TAG
|
||||
FROM $AA_DOCKER_TAG
|
||||
|
||||
RUN cd /home/allianceauth
|
||||
WORKDIR ${AUTH_HOME}
|
||||
|
||||
COPY /conf/requirements.txt requirements.txt
|
||||
RUN pip install -r requirements.txt
|
||||
RUN --mount=type=cache,target=~/.cache \
|
||||
pip install -r requirements.txt
|
||||
|
||||
@@ -35,7 +35,7 @@ To ensure the dashboard widgets have a unified style, we provide a template part
|
||||
To use it, you can use the following code in your dashboard widget template:
|
||||
|
||||
```django
|
||||
<div id="my-app-dashboard-widget" class="col-12 align-self-stretch py-2">
|
||||
<div id="my-app-dashboard-widget" class="col-12 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% translate "My Widget Title" as widget_title %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mumble
|
||||
# Mumble (Docker)
|
||||
|
||||
An alternate install guide for Mumble using Docker, better suited to an Alliance Auth Docker install
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Openfire
|
||||
# Openfire (Docker)
|
||||
|
||||
An alternate install guide for Openfire using Docker, better suited to an Alliance Auth Docker install
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# TeamSpeak 3
|
||||
# TeamSpeak 3 (Docker)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -181,13 +181,17 @@ If you don't plan on running the database on the same server as auth you still n
|
||||
|
||||
### Redis and Other Tools
|
||||
|
||||
A few extra utilities are also required for installation of packages.
|
||||
A few extra utilities are also required for the installation of packages.
|
||||
|
||||
::::{tabs}
|
||||
|
||||
:::{group-tab} Ubuntu 2004, 2204
|
||||
|
||||
```shell
|
||||
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
|
||||
sudo apt-get update
|
||||
sudo apt-get install unzip git redis-server curl libssl-dev libbz2-dev libffi-dev build-essential pkg-config
|
||||
```
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ authors = [
|
||||
requires-python = ">=3.8"
|
||||
classifiers = [
|
||||
"Environment :: Web Environment",
|
||||
"Framework :: Celery",
|
||||
"Framework :: Django",
|
||||
"Framework :: Django :: 4.2",
|
||||
"Intended Audience :: Developers",
|
||||
@@ -49,6 +50,7 @@ dependencies = [
|
||||
"django-esi>=5",
|
||||
"django-redis>=5.2",
|
||||
"django-registration<3.4,>=3.3",
|
||||
"django-solo",
|
||||
"django-sortedm2m",
|
||||
"dnspython",
|
||||
"mysqlclient>=2.1",
|
||||
|
||||
Reference in New Issue
Block a user