diff --git a/src/strass/live_settings/__init__.py b/src/strass/live_settings/__init__.py deleted file mode 100644 index 7b7e019a9ace42a69086a2ba16c7d621b3d5f3c8..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/__init__.py +++ /dev/null @@ -1,59 +0,0 @@ -from datetime import datetime - -from django.core.cache import cache -from django.db import OperationalError, ProgrammingError - -__LIVE_SETTING_EDITOR = "LiveSettingEditor" - - -def get_live_settings_editor_group_name(): - return __LIVE_SETTING_EDITOR - - -class LiveSettings(object): - def __setattr__(self, key, value, *args, **kwargs): - try: - from live_settings.models import LiveSettings - - if value is None: - LiveSettings.objects.filter(key=key).delete() - else: - LiveSettings.objects.update_or_create(key=key, defaults=dict(value=str(value))) - except (ProgrammingError, OperationalError): - return super().__setattr__(key, value) - - def __getattribute__(self, key): - as_int = False - as_bool = False - as_date = False - if key.endswith("__int"): - key = key[:-5] - as_int = True - if key.endswith("__bool"): - key = key[:-6] - as_bool = True - if key.endswith("__date"): - key = key[:-6] - as_date = True - live_settings_dict = cache.get("live_settings_dict") - if live_settings_dict is None: - try: - from live_settings.models import LiveSettings - - live_settings_dict = dict(LiveSettings.objects.values_list("key", "value")) - cache.set("live_settings_dict", live_settings_dict) - except (ProgrammingError, OperationalError): - return super().__getattribute__(key) - value = live_settings_dict.get(key, None) - if value is None: - return value - if as_int: - return int(value) - if as_bool: - return str(value).upper() == "TRUE" - if as_date: - return datetime.strptime(str(value), "%Y-%m-%d").date() - return value - - -live_settings = LiveSettings() diff --git a/src/strass/live_settings/admin.py b/src/strass/live_settings/admin.py deleted file mode 100644 index 31c733caf05f3f49bceb70104dab46dd989deab8..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/admin.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib import admin - -from live_settings import models - - -class LiveSettingsAdmin(admin.ModelAdmin): - list_display = ("key", "last_edition_date") - readonly_fields = ["last_edition_date"] - - -admin.site.register(models.LiveSettings, LiveSettingsAdmin) diff --git a/src/strass/live_settings/context_processors.py b/src/strass/live_settings/context_processors.py deleted file mode 100644 index 9fc38cc3fe1c0f34998ba57df5194cbbe2655749..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/context_processors.py +++ /dev/null @@ -1,5 +0,0 @@ -from live_settings import live_settings - - -def processors(request): - return dict(live_settings=live_settings) diff --git a/src/strass/live_settings/forms.py b/src/strass/live_settings/forms.py deleted file mode 100644 index c636c9a796c9956a2122bb8dc100043cc0069844..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/forms.py +++ /dev/null @@ -1,12 +0,0 @@ -from django import forms - -from live_settings import models - - -class LiveSettingsForm(forms.ModelForm): - next = forms.CharField(widget=forms.HiddenInput(), required=True) - - class Meta: - model = models.LiveSettings - fields = ("value",) - widgets = {"value": forms.HiddenInput()} diff --git a/src/strass/live_settings/migrations/0001_initial.py b/src/strass/live_settings/migrations/0001_initial.py deleted file mode 100644 index cabe4e90c83a589304b6d4a795de420cfbfd3a7c..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/migrations/0001_initial.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2.5 on 2019-11-20 10:20 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='LiveSettings', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('key', models.CharField(max_length=256, unique=True, validators=[django.core.validators.RegexValidator(code='invalid_live_settings_key', message='LiveSettings key must must be Alphanumeric and start with a letter: <code>^[a-zA-Z][\\w]*$</code>.', regex='^[a-zA-Z][\\w]*$')])), - ('value', models.TextField(blank=True, null=True)), - ('last_edition_date', models.DateTimeField()), - ], - ), - ] diff --git a/src/strass/live_settings/migrations/0002_create_group_settings_changer.py b/src/strass/live_settings/migrations/0002_create_group_settings_changer.py deleted file mode 100644 index efcdf440c9c75a6b329f2caf6f22abebc6a72982..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/migrations/0002_create_group_settings_changer.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib.auth import get_permission_codename -from django.contrib.auth.models import Permission, Group -from django.contrib.contenttypes.models import ContentType -from django.db import migrations - - -def migration_code(apps, schema_editor): - # inspired by django.contrib.auth.management.create_permissions - group, _ = Group.objects.get_or_create(name="LiveSettingEditor") - - for klass in [ - apps.get_model("live_settings", "LiveSettings"), - ]: - ct = ContentType.objects.get_for_model(klass) - opts = klass._meta - - for action in klass._meta.default_permissions: - perm, _ = Permission.objects.get_or_create( - codename=get_permission_codename(action, opts), - name='Can %s %s' % (action, opts.verbose_name_raw), - content_type=ct) - group.permissions.add(perm) - - -def reverse_code(apps, schema_editor): - Group.objects.filter(name="LiveSettingEditor").delete() - - -class Migration(migrations.Migration): - dependencies = [ - ('live_settings', '0001_initial'), - ] - - operations = [ - migrations.RunPython(migration_code, reverse_code=reverse_code), - ] diff --git a/src/strass/live_settings/migrations/0003_auto_20200311_1037.py b/src/strass/live_settings/migrations/0003_auto_20200311_1037.py deleted file mode 100644 index 498cafe9b0b7b96e8db499fff04b4b38c307d4a1..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/migrations/0003_auto_20200311_1037.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.5 on 2020-03-11 09:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('live_settings', '0002_create_group_settings_changer'), - ] - - operations = [ - migrations.AlterModelOptions( - name='livesettings', - options={'verbose_name': 'Live setting', 'verbose_name_plural': 'Live settings'}, - ), - ] diff --git a/src/strass/live_settings/migrations/0004_alter_livesettings_id.py b/src/strass/live_settings/migrations/0004_alter_livesettings_id.py deleted file mode 100644 index dc6d6878e2a96de8e0e96a92daa5e5318ea8067b..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/migrations/0004_alter_livesettings_id.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.4 on 2021-07-01 09:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('live_settings', '0003_auto_20200311_1037'), - ] - - operations = [ - migrations.AlterField( - model_name='livesettings', - name='id', - field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), - ), - ] diff --git a/src/strass/live_settings/migrations/__init__.py b/src/strass/live_settings/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/strass/live_settings/models.py b/src/strass/live_settings/models.py deleted file mode 100644 index bec35c8903b6424cb1536c9d0b083f5d1f70fc65..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/models.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import unicode_literals - -from django.core.cache import cache -from django.core.validators import RegexValidator -from django.db import models -from django.db.models.signals import post_save, post_delete -from django.dispatch import receiver -from django.utils import timezone -from django.utils.safestring import mark_safe - - -class LiveSettings(models.Model): - class Meta: - verbose_name = "Live setting" - verbose_name_plural = "Live settings" - - regex = "^[a-zA-Z][\\w]*$" - key = models.CharField( - max_length=256, - unique=True, - validators=( - RegexValidator( - regex=regex, - message=mark_safe( - "LiveSettings key must must be Alphanumeric and start with a letter: " "<code>%s</code>." % regex - ), - code="invalid_live_settings_key", - ), - ), - ) - value = models.TextField( - blank=True, - null=True, - ) - last_edition_date = models.DateTimeField() - - def save(self, *args, **kwargs): - self.last_edition_date = timezone.now() - super().save(*args, **kwargs) - - -@receiver(post_save, sender=LiveSettings) -@receiver(post_delete, sender=LiveSettings) -def flush_live_settings_in_cache(*args, **kwargs): - cache.delete("live_settings_dict") diff --git a/src/strass/live_settings/templates/admin/index.html b/src/strass/live_settings/templates/admin/index.html deleted file mode 100644 index ff93bb55311fe33270af1e21b89df56c02b7045a..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/templates/admin/index.html +++ /dev/null @@ -1,57 +0,0 @@ -{% extends "admin/index.html" %} -{% load i18n basetheme_bootstrap %} - -{% block extrastyle %} -{{ block.super }} -<style> -#content-related{ - background: none; -} -#content-related .module{ - background: var(--darkened-bg); -} -#site-wide-commands form{ - margin:15px 7px; -} -</style> -{% endblock %} - -{% block sidebar %} -<div id="content-related"> - {% if perms.live_settings.change_livesettings %} - <div class="module" id="site-wide-commands"> - <h2>{% trans 'Site wide settings' %}</h2> - {%include_if_exists "live_settings/sitewidecommands.html" %} - </div> - {%endif%} - - <div class="module" id="recent-actions-module"> - <h2>{% trans 'Recent actions' %}</h2> - <h3>{% trans 'My actions' %}</h3> - {% load log %} - {% get_admin_log 10 as admin_log for_user user %} - {% if not admin_log %} - <p>{% trans 'None available' %}</p> - {% else %} - <ul class="actionlist"> - {% for entry in admin_log %} - <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}"> - {% if entry.is_deletion or not entry.get_admin_url %} - {{ entry.object_repr }} - {% else %} - <a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a> - {% endif %} - <br> - {% if entry.content_type %} - <span class="mini quiet">{% filter capfirst %}{{ entry.content_type }}{% endfilter %}</span> - {% else %} - <span class="mini quiet">{% trans 'Unknown content' %}</span> - {% endif %} - </li> - {% endfor %} - </ul> - {% endif %} - <hr/> - </div> -</div> -{% endblock %} \ No newline at end of file diff --git a/src/strass/live_settings/tests.py b/src/strass/live_settings/tests.py deleted file mode 100644 index ade60b313bb01eb822125bf03b5c86a6f9f9be29..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/tests.py +++ /dev/null @@ -1,80 +0,0 @@ -import logging -from unittest import TestCase - -from django.contrib.auth import get_user_model -from django.contrib.auth.models import Permission -from django.contrib.contenttypes.models import ContentType -from django.core import management -from django.core.cache import cache -from django.test import TestCase as DjangoTestCase -from django.urls import reverse - -from live_settings import live_settings, models -from live_settings.tools import set_default_live_setting - -logger = logging.getLogger(__name__) - - -class LiveSettingsTestCase(DjangoTestCase): - def setUp(self) -> None: - super().setUp() - ################################################################################ - self.user = get_user_model().objects.create( - username="root", - ) - - def test_get_value(self): - self.assertIsNone(live_settings.toto) - models.LiveSettings.objects.create(key="toto", value="tata") - self.assertIsNotNone(live_settings.toto) - self.assertEqual(live_settings.toto, "tata") - - def test_get_set(self): - live_settings.tralala = 1 - self.assertEqual(str(live_settings.tralala), "1") - live_settings.tralala = None - self.assertIsNone(live_settings.tralala) - - def test_view_works(self): - form_data = dict(value="titi", next="/") - url = reverse('live_settings:update', args=["toto"]) - - response = self.client.post(url, form_data) - self.assertEqual(response.status_code, 302) - self.assertNotEqual(live_settings.toto, form_data["value"]) - - self.client.force_login(self.user) - - response = self.client.post(url, form_data) - self.assertEqual(response.status_code, 302) - self.assertNotEqual(live_settings.toto, form_data["value"]) - - change = Permission.objects.get( - content_type=ContentType.objects.get_for_model(models.LiveSettings), codename__startswith="change" - ) - self.user.user_permissions.add(change) - - response = self.client.get(url) - self.assertEqual(response.status_code, 403) - self.assertNotEqual(live_settings.toto, form_data["value"]) - - response = self.client.post(url, dict(value=form_data["value"])) - self.assertEqual(response.status_code, 400) - self.assertNotEqual(live_settings.toto, form_data["value"]) - - response = self.client.post(url, form_data) - self.assertEqual(response.status_code, 302) - self.assertEqual(live_settings.toto, form_data["value"]) - - -class LiveSettingsNoDBTestCase(TestCase): - def test_get_value(self): - management.call_command("migrate", "live_settings", "zero", no_input=True, skip_checks=True) - cache.delete("live_settings_dict") - try: - ex = live_settings.tralala - except Exception as e: - ex = e - assert isinstance(ex, AttributeError) - live_settings.tralala = 1 - set_default_live_setting("tralala", 2) diff --git a/src/strass/live_settings/tools.py b/src/strass/live_settings/tools.py deleted file mode 100644 index dee56ab3fff56a8e1f90d6e191921474e1e7cbac..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/tools.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.core.cache import cache -from django.db import OperationalError, ProgrammingError - - -def set_default_live_setting(key, value): - try: - from live_settings.models import LiveSettings - - LiveSettings.objects.get_or_create(key=key, defaults=dict(value=str(value))) - cache.delete("live_settings_dict") - except (ProgrammingError, OperationalError): - pass diff --git a/src/strass/live_settings/urls.py b/src/strass/live_settings/urls.py deleted file mode 100644 index be3156db944122a5bced9ae97b96e55728540b5e..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/urls.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.urls import re_path - -from live_settings import views - -app_name = "live_settings" -urlpatterns = [re_path(r"^update/(?P<slug>[a-zA-Z][\w]*)/$", views.change_value, name="update")] diff --git a/src/strass/live_settings/views.py b/src/strass/live_settings/views.py deleted file mode 100644 index 2a20f019516b6b8080feb0ff1bbf4241fbe82f68..0000000000000000000000000000000000000000 --- a/src/strass/live_settings/views.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.contrib.auth.decorators import permission_required -from django.http import HttpResponseForbidden, HttpResponseBadRequest -from django.shortcuts import redirect - -from live_settings import forms -from live_settings import live_settings - - -@permission_required("live_settings.change_livesettings") -def change_value(request, slug): - if request.method != "POST": - return HttpResponseForbidden() - - form = forms.LiveSettingsForm(data=request.POST) - if not form.is_valid(): - return HttpResponseBadRequest() - - setattr(live_settings, slug, form.cleaned_data["value"]) - - return redirect(form.cleaned_data["next"]) diff --git a/src/strass/requirements.txt b/src/strass/requirements.txt index 1bd9dab2bdc209d9eb327b540d4de7b4afee57f9..2c890cf702b2486b123df0e90ba6852edfe3ca86 100644 --- a/src/strass/requirements.txt +++ b/src/strass/requirements.txt @@ -9,6 +9,8 @@ django-basetheme-bootstrap>=1.8.7 django-kubernetes-probes>=1.1 --extra-index-url https://gitlab.pasteur.fr/api/v4/projects/hub%2Fdjango-csp-mail-reports/packages/pypi/simple django-csp-mail-reports>=1.0 +--extra-index-url https://gitlab.pasteur.fr/api/v4/projects/hub%2Fdjango-live-settings/packages/pypi/simple +django-live-settings>=1.0.1 django-formtools csscompressor coverage