diff --git a/allianceauth/analytics/admin.py b/allianceauth/analytics/admin.py index 383bbbe2..497f2d7c 100644 --- a/allianceauth/analytics/admin.py +++ b/allianceauth/analytics/admin.py @@ -1,15 +1,16 @@ from django.contrib import admin from .models import AnalyticsIdentifier, AnalyticsTokens +from solo.admin import SingletonModelAdmin @admin.register(AnalyticsIdentifier) -class AnalyticsIdentifierAdmin(admin.ModelAdmin): +class AnalyticsIdentifierAdmin(SingletonModelAdmin): search_fields = ['identifier', ] - list_display = ('identifier',) + list_display = ['identifier', ] @admin.register(AnalyticsTokens) class AnalyticsTokensAdmin(admin.ModelAdmin): search_fields = ['name', ] - list_display = ('name', 'type',) + list_display = ['name', 'type', ] diff --git a/allianceauth/analytics/migrations/0010_alter_analyticsidentifier_options.py b/allianceauth/analytics/migrations/0010_alter_analyticsidentifier_options.py new file mode 100644 index 00000000..7c1993e9 --- /dev/null +++ b/allianceauth/analytics/migrations/0010_alter_analyticsidentifier_options.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.16 on 2024-12-11 02:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('analytics', '0009_remove_analyticstokens_ignore_paths_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='analyticsidentifier', + options={'verbose_name': 'Analytics Identifier'}, + ), + ] diff --git a/allianceauth/analytics/models.py b/allianceauth/analytics/models.py index ddee495a..16ea0221 100644 --- a/allianceauth/analytics/models.py +++ b/allianceauth/analytics/models.py @@ -1,23 +1,19 @@ +from typing import Literal from django.db import models -from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ - +from solo.models import SingletonModel from uuid import uuid4 -class AnalyticsIdentifier(models.Model): +class AnalyticsIdentifier(SingletonModel): - identifier = models.UUIDField( - default=uuid4, - editable=False) + identifier = models.UUIDField(default=uuid4, editable=False) - def save(self, *args, **kwargs): - if not self.pk and AnalyticsIdentifier.objects.exists(): - # Force a single object - raise ValidationError('There is can be only one \ - AnalyticsIdentifier instance') - self.pk = self.id = 1 # If this happens to be deleted and recreated, force it to be 1 - return super().save(*args, **kwargs) + def __str__(self) -> Literal['Analytics Identifier']: + return "Analytics Identifier" + + class Meta: + verbose_name = "Analytics Identifier" class AnalyticsTokens(models.Model): diff --git a/allianceauth/analytics/tasks.py b/allianceauth/analytics/tasks.py index cc9ef160..d0a76c30 100644 --- a/allianceauth/analytics/tasks.py +++ b/allianceauth/analytics/tasks.py @@ -5,6 +5,7 @@ from django.apps import apps from celery import shared_task from .models import AnalyticsTokens, AnalyticsIdentifier from .utils import ( + existence_baremetal_or_docker, install_stat_addons, install_stat_tokens, install_stat_users) @@ -67,8 +68,8 @@ def analytics_event(namespace: str, value=value).apply_async(priority=9) -@shared_task() -def analytics_daily_stats(): +@shared_task +def analytics_daily_stats() -> None: """Celery Task: Do not call directly Gathers a series of daily statistics @@ -77,6 +78,7 @@ def analytics_daily_stats(): users = install_stat_users() tokens = install_stat_tokens() addons = install_stat_addons() + existence_type = existence_baremetal_or_docker() logger.debug("Running Daily Analytics Upload") analytics_event(namespace='allianceauth.analytics', @@ -84,6 +86,11 @@ def analytics_daily_stats(): label='existence', value=1, event_type='Stats') + analytics_event(namespace='allianceauth.analytics', + task='send_install_stats', + label=existence_type, + value=1, + event_type='Stats') analytics_event(namespace='allianceauth.analytics', task='send_install_stats', label='users', @@ -99,7 +106,6 @@ def analytics_daily_stats(): label='addons', value=addons, event_type='Stats') - for appconfig in apps.get_app_configs(): if appconfig.label in [ "django_celery_beat", @@ -135,7 +141,7 @@ def analytics_daily_stats(): event_type='Stats') -@shared_task() +@shared_task def send_ga_tracking_celery_event( measurement_id: str, secret: str, @@ -165,7 +171,7 @@ def send_ga_tracking_celery_event( } payload = { - 'client_id': AnalyticsIdentifier.objects.get(id=1).identifier.hex, + 'client_id': AnalyticsIdentifier.get_solo().identifier.hex, "user_properties": { "allianceauth_version": { "value": __version__ diff --git a/allianceauth/analytics/tests/test_models.py b/allianceauth/analytics/tests/test_models.py index 452c4eaa..979f2720 100644 --- a/allianceauth/analytics/tests/test_models.py +++ b/allianceauth/analytics/tests/test_models.py @@ -1,9 +1,8 @@ from allianceauth.analytics.models import AnalyticsIdentifier -from django.core.exceptions import ValidationError from django.test.testcases import TestCase -from uuid import UUID, uuid4 +from uuid import uuid4 # Identifiers @@ -14,14 +13,4 @@ uuid_2 = "7aa6bd70701f44729af5e3095ff4b55c" class TestAnalyticsIdentifier(TestCase): def test_identifier_random(self): - self.assertNotEqual(AnalyticsIdentifier.objects.get(), uuid4) - - def test_identifier_singular(self): - AnalyticsIdentifier.objects.all().delete() - AnalyticsIdentifier.objects.create(identifier=uuid_1) - # Yeah i have multiple asserts here, they all do the same thing - with self.assertRaises(ValidationError): - AnalyticsIdentifier.objects.create(identifier=uuid_2) - self.assertEqual(AnalyticsIdentifier.objects.count(), 1) - self.assertEqual(AnalyticsIdentifier.objects.get( - pk=1).identifier, UUID(uuid_1)) + self.assertNotEqual(AnalyticsIdentifier.get_solo(), uuid4) diff --git a/allianceauth/analytics/utils.py b/allianceauth/analytics/utils.py index e8c57927..fa50084f 100644 --- a/allianceauth/analytics/utils.py +++ b/allianceauth/analytics/utils.py @@ -1,3 +1,4 @@ +import os from django.apps import apps from allianceauth.authentication.models import User from esi.models import Token @@ -34,3 +35,16 @@ def install_stat_addons() -> int: The Number of Installed Apps""" addons = len(list(apps.get_app_configs())) return addons + + +def existence_baremetal_or_docker() -> str: + """Checks the Installation Type of an install + + Returns + ------- + str + existence_baremetal or existence_docker""" + docker_tag = os.getenv('AA_DOCKER_TAG') + if docker_tag: + return "existence_docker" + return "existence_baremetal" diff --git a/allianceauth/project_template/project_name/settings/base.py b/allianceauth/project_template/project_name/settings/base.py index 19bdbe77..56e7c493 100644 --- a/allianceauth/project_template/project_name/settings/base.py +++ b/allianceauth/project_template/project_name/settings/base.py @@ -44,8 +44,10 @@ INSTALLED_APPS = [ 'allianceauth.theme.materia', "allianceauth.custom_css", 'allianceauth.crontab', + 'sri', ] +SRI_ALGORITHM = "sha512" SECRET_KEY = "wow I'm a really bad default secret key" # Celery configuration diff --git a/allianceauth/templates/bundles/auth-base-css.html b/allianceauth/templates/bundles/auth-base-css.html index 0ee2e7ce..ce7b4373 100644 --- a/allianceauth/templates/bundles/auth-base-css.html +++ b/allianceauth/templates/bundles/auth-base-css.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/css/auth-base.css' %} diff --git a/allianceauth/templates/bundles/auth-framework-css.html b/allianceauth/templates/bundles/auth-framework-css.html index 9f1c038a..1722377a 100644 --- a/allianceauth/templates/bundles/auth-framework-css.html +++ b/allianceauth/templates/bundles/auth-framework-css.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/framework/css/auth-framework.css' %} diff --git a/allianceauth/templates/bundles/bootstrap-css.html b/allianceauth/templates/bundles/bootstrap-css.html index bed760ba..88147119 100644 --- a/allianceauth/templates/bundles/bootstrap-css.html +++ b/allianceauth/templates/bundles/bootstrap-css.html @@ -1,4 +1,6 @@ {% load static %} +{% load sri %} + {% if NIGHT_MODE %} {% if debug %} @@ -6,7 +8,7 @@ {% else %} - + {% sri_static 'allianceauth/css/themes/darkly/darkly.min.css' %} {% endif %} {% else %} {% if debug %} @@ -14,7 +16,7 @@ {% else %} - + {% sri_static 'allianceauth/css/themes/flatly/flatly.min.css' %} {% endif %} {% endif %} diff --git a/allianceauth/templates/bundles/checkbox-css.html b/allianceauth/templates/bundles/checkbox-css.html index f400d36c..1f2cc08e 100644 --- a/allianceauth/templates/bundles/checkbox-css.html +++ b/allianceauth/templates/bundles/checkbox-css.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/css/checkbox.css' %} diff --git a/allianceauth/templates/bundles/evetime-js.html b/allianceauth/templates/bundles/evetime-js.html index 63b712c3..6611516e 100644 --- a/allianceauth/templates/bundles/evetime-js.html +++ b/allianceauth/templates/bundles/evetime-js.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/js/eve-time.js' %} diff --git a/allianceauth/templates/bundles/filterdropdown-js.html b/allianceauth/templates/bundles/filterdropdown-js.html index 677fa536..41a0e3bd 100644 --- a/allianceauth/templates/bundles/filterdropdown-js.html +++ b/allianceauth/templates/bundles/filterdropdown-js.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/js/filterDropDown/filterDropDown.min.js' %} diff --git a/allianceauth/templates/bundles/jquery-ui-css.html b/allianceauth/templates/bundles/jquery-ui-css.html index 3bf4d1a3..9177c19e 100644 --- a/allianceauth/templates/bundles/jquery-ui-css.html +++ b/allianceauth/templates/bundles/jquery-ui-css.html @@ -1,5 +1,6 @@ -{% load static %} - - + +{% load sri %} + +{% sri_static 'allianceauth/js/jquery-ui/1.13.2/css/jquery-ui.min.css' %} diff --git a/allianceauth/templates/bundles/moment-js.html b/allianceauth/templates/bundles/moment-js.html index a094b4be..802411b9 100644 --- a/allianceauth/templates/bundles/moment-js.html +++ b/allianceauth/templates/bundles/moment-js.html @@ -1,7 +1,19 @@ +{% load i18n %} + + {% if locale and LANGUAGE_CODE != 'en' %} - + {% get_current_language as LANGUAGE_CODE %} + {% get_language_info for LANGUAGE_CODE as lang %} + + {% if lang.code == 'zh-hans' %} + + + {% else %} + + + {% endif %} {% endif %} diff --git a/allianceauth/templates/bundles/refresh-notification-icon-js.html b/allianceauth/templates/bundles/refresh-notification-icon-js.html index 88f3d16f..69cc53b8 100644 --- a/allianceauth/templates/bundles/refresh-notification-icon-js.html +++ b/allianceauth/templates/bundles/refresh-notification-icon-js.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/js/refresh-notification-icon.js' %} diff --git a/allianceauth/templates/bundles/refresh-notifications-js.html b/allianceauth/templates/bundles/refresh-notifications-js.html index 27622b3e..50b5e8f4 100644 --- a/allianceauth/templates/bundles/refresh-notifications-js.html +++ b/allianceauth/templates/bundles/refresh-notifications-js.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/js/refresh_notifications.js' %} diff --git a/allianceauth/templates/bundles/timerboard-js.html b/allianceauth/templates/bundles/timerboard-js.html index 8cf6f353..8bad97d9 100644 --- a/allianceauth/templates/bundles/timerboard-js.html +++ b/allianceauth/templates/bundles/timerboard-js.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/js/timerboard.js' %} diff --git a/allianceauth/templates/bundles/timers-js.html b/allianceauth/templates/bundles/timers-js.html index b9690202..a570a10d 100644 --- a/allianceauth/templates/bundles/timers-js.html +++ b/allianceauth/templates/bundles/timers-js.html @@ -1,3 +1,3 @@ -{% load static %} +{% load sri %} - +{% sri_static 'allianceauth/js/timers.js' %} diff --git a/allianceauth/timerboard/migrations/0007_alter_timer_structure.py b/allianceauth/timerboard/migrations/0007_alter_timer_structure.py new file mode 100644 index 00000000..26513513 --- /dev/null +++ b/allianceauth/timerboard/migrations/0007_alter_timer_structure.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.17 on 2025-01-06 17:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("timerboard", "0006_alter_timer_objective_alter_timer_structure_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="timer", + name="structure", + field=models.CharField( + choices=[ + ("POCO", "POCO"), + ("Orbital Skyhook", "Orbital Skyhook"), + ("I-HUB", "Sovereignty Hub"), + ("TCU", "TCU"), + ("POS[S]", "POS [S]"), + ("POS[M]", "POS [M]"), + ("POS[L]", "POS [L]"), + ("Astrahus", "Astrahus"), + ("Fortizar", "Fortizar"), + ("Keepstar", "Keepstar"), + ("Raitaru", "Raitaru"), + ("Azbel", "Azbel"), + ("Sotiyo", "Sotiyo"), + ("Athanor", "Athanor"), + ("Tatara", "Tatara"), + ("Pharolux Cyno Beacon", "Cyno Beacon"), + ("Tenebrex Cyno Jammer", "Cyno Jammer"), + ("Ansiblex Jump Gate", "Ansiblex Jump Gate"), + ("Mercenary Den", "Mercenary Den"), + ("Moon Mining Cycle", "Moon Mining Cycle"), + ("Metenox Moon Drill", "Metenox Moon Drill"), + ("Other", "Other"), + ], + default="Other", + max_length=254, + ), + ), + ] diff --git a/allianceauth/timerboard/models.py b/allianceauth/timerboard/models.py index d4127c9b..bf6f9b08 100644 --- a/allianceauth/timerboard/models.py +++ b/allianceauth/timerboard/models.py @@ -1,6 +1,6 @@ from django.contrib.auth.models import User from django.db import models -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from allianceauth.eveonline.models import EveCharacter from allianceauth.eveonline.models import EveCorporationInfo @@ -23,7 +23,7 @@ class Timer(models.Model): POCO = "POCO", _("POCO") ORBITALSKYHOOK = "Orbital Skyhook", _("Orbital Skyhook") - IHUB = "I-HUB", _("I-HUB") + IHUB = "I-HUB", _("Sovereignty Hub") TCU = "TCU", _("TCU") # Pending Remval POSS = "POS[S]", _("POS [S]") POSM = "POS[M]", _("POS [M]") @@ -36,9 +36,10 @@ class Timer(models.Model): SOTIYO = "Sotiyo", _("Sotiyo") ATHANOR = "Athanor", _("Athanor") TATARA = "Tatara", _("Tatara") - PHAROLUX = "Pharolux Cyno Beacon", _("Pharolux Cyno Beacon") - TENEBREX = "Tenebrex Cyno Jammer", _("Tenebrex Cyno Jammer") + PHAROLUX = "Pharolux Cyno Beacon", _("Cyno Beacon") + TENEBREX = "Tenebrex Cyno Jammer", _("Cyno Jammer") ANSIBLEX = "Ansiblex Jump Gate", _("Ansiblex Jump Gate") + MERCDEN = "Mercenary Den", _("Mercenary Den") MOONPOP = "Moon Mining Cycle", _("Moon Mining Cycle") METENOX = "Metenox Moon Drill", _("Metenox Moon Drill") OTHER = "Other", _("Other") diff --git a/allianceauth/timerboard/templates/timerboard/timertable.html b/allianceauth/timerboard/templates/timerboard/timertable.html index c1d5c818..014b01e8 100644 --- a/allianceauth/timerboard/templates/timerboard/timertable.html +++ b/allianceauth/timerboard/templates/timerboard/timertable.html @@ -19,7 +19,6 @@ {% for timer in timers %}