From 57eaa85e0f91a2e5c5b1ab912f8657ce1ec363e9 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Tue, 18 Feb 2025 21:57:02 +0100 Subject: [PATCH] feat(shared): Add a view for exporting members to a mailing-list --- bds/urls.py | 7 ++++++ gestioasso/settings/local.py | 3 +++ gestioasso/settings_bds.py | 3 +++ gestioasso/settings_cof.py | 3 +++ gestioncof/urls.py | 14 +++++++++++ shared/views.py | 45 ++++++++++++++++++++++++++++++++++-- 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/bds/urls.py b/bds/urls.py index 95065773..68d780df 100644 --- a/bds/urls.py +++ b/bds/urls.py @@ -1,6 +1,7 @@ from django.urls import path from bds import views +from shared.views import SympaListView app_name = "bds" urlpatterns = [ @@ -21,4 +22,10 @@ urlpatterns = [ name="members.expired", ), path("members/reset", views.ResetMembershipView.as_view(), name="members.reset"), + # Sympa export view + path( + "sympa/members/", + SympaListView.as_view(filters={"bds__is_member": True}), + name="export.sympa", + ), ] diff --git a/gestioasso/settings/local.py b/gestioasso/settings/local.py index 2cba6a10..c6a22e64 100644 --- a/gestioasso/settings/local.py +++ b/gestioasso/settings/local.py @@ -27,6 +27,9 @@ ALLOWED_HOSTS = [] DEBUG = True EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" +SYMPA_PASSWORD = b"sympa" +SYMPA_USERNAME = b"sympa" + if TESTING: PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] diff --git a/gestioasso/settings_bds.py b/gestioasso/settings_bds.py index 231ae101..e640b222 100644 --- a/gestioasso/settings_bds.py +++ b/gestioasso/settings_bds.py @@ -26,6 +26,9 @@ EMAIL_HOST = credentials.get("EMAIL_HOST") DEFAULT_AUTO_FIELD = "django.db.models.AutoField" +SYMPA_PASSWORD = credentials["SYMPA_PASSWORD"].encode() +SYMPA_USERNAME = credentials["SYMPA_USERNAME"].encode() + ## # Installed Apps configuration diff --git a/gestioasso/settings_cof.py b/gestioasso/settings_cof.py index 6bccefc2..893aaec4 100644 --- a/gestioasso/settings_cof.py +++ b/gestioasso/settings_cof.py @@ -30,6 +30,9 @@ LDAP_SERVER_URL = credentials.get("LDAP_SERVER_URL") DEFAULT_AUTO_FIELD = "django.db.models.AutoField" +SYMPA_PASSWORD = credentials["SYMPA_PASSWORD"].encode() +SYMPA_USERNAME = credentials["SYMPA_USERNAME"].encode() + ## # Installed Apps configuration diff --git a/gestioncof/urls.py b/gestioncof/urls.py index d0ba75c7..624f8e22 100644 --- a/gestioncof/urls.py +++ b/gestioncof/urls.py @@ -4,6 +4,16 @@ from django.views.generic.base import TemplateView from django_cas_ng import views as django_cas_views from gestioncof import csv_views, views +from shared.views import SympaListView + +sympa_patterns = [ + path( + f"{mailing}/", + SympaListView.as_view(filters={f"profile__mailing_{mailing}": True}), + name=f"sympa.{mailing}", + ) + for mailing in ["bda", "bda_revente", "cof", "unernestaparis"] +] export_patterns = [ path("members", views.export_members, name="export.members"), @@ -162,4 +172,8 @@ urlpatterns = [ # Clubs # ----- path("clubs/", include(clubs_patterns)), + # ----- + # Sympa export + # ----- + path("sympa/", include(sympa_patterns)), ] diff --git a/shared/views.py b/shared/views.py index a1ffb185..fbff4ec0 100644 --- a/shared/views.py +++ b/shared/views.py @@ -1,12 +1,53 @@ +import base64 from collections import namedtuple +from typing import Any from dal import autocomplete +from django.conf import settings +from django.contrib.auth import get_user_model from django.core.exceptions import ImproperlyConfigured -from django.http import Http404 -from django.views.generic import TemplateView +from django.http import Http404, HttpResponse +from django.views.generic import TemplateView, View from shared.autocomplete import ModelSearch +User = get_user_model() + + +class SympaListView(View): + realm = "sympa" + + username = settings.SYMPA_USERNAME + password = settings.SYMPA_PASSWORD + + filters: dict[str, Any] = {} + + def dispatch(self, request, *args, **kwargs): + if "HTTP_AUTHORIZATION" in request.META: + auth = request.META["HTTP_AUTHORIZATION"].split() + + if len(auth) == 2 and auth[0].lower() == "basic": + name, passwd = base64.b64decode(auth[1]).split(b":") + + if name == self.username and passwd == self.password: + return self.render_to_response(request, *args, **kwargs) + + return HttpResponse( + status=401, headers={"WWW-Authenticate": f'Basic realm="{self.realm}"'} + ) + + def render_to_response(self, request, *args, **kwargs): + """ + Renders a list of emails in a text response. + """ + + users = User.objects.filter(**self.filters) + + return HttpResponse( + b"\n".join(u.email.encode("utf-8") for u in users if u.email), + content_type="text/plain", + ) + class Select2QuerySetView(ModelSearch, autocomplete.Select2QuerySetView): """Compatibility layer between ModelSearch and Select2QuerySetView."""