From 23770288f64fd692a8e3466748f2e9b22d0cbfa9 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 6 Oct 2022 11:55:02 +0200 Subject: [PATCH] members registration: send notification to group leiters when mails are confirmed --- jdav_web/mailer/mailutils.py | 14 +- .../members/locale/de/LC_MESSAGES/django.po | 142 +++++++++--------- jdav_web/members/models.py | 43 +++++- jdav_web/members/views.py | 5 +- 4 files changed, 122 insertions(+), 82 deletions(-) diff --git a/jdav_web/mailer/mailutils.py b/jdav_web/mailer/mailutils.py index 3c4c111..ac4ea64 100644 --- a/jdav_web/mailer/mailutils.py +++ b/jdav_web/mailer/mailutils.py @@ -5,6 +5,8 @@ import os NOT_SENT, SENT, PARTLY_SENT = 0, 1, 2 HOST = os.environ.get('DJANGO_ALLOWED_HOST', 'localhost:8000').split(",")[0] +PROTOCOL = os.environ.get('DJANGO_PROTOCOL', 'https') +BASE_URL = os.environ.get('DJANGO_BASE_URL', HOST) def send(subject, content, sender, recipients, message_id=None, reply_to=None, @@ -46,7 +48,7 @@ def send(subject, content, sender, recipients, message_id=None, reply_to=None, def get_content(content, registration_complete=True): - url = "https://{}/newsletter/unsubscribe".format(HOST) + url = prepend_base_url("/newsletter/unsubscribe") prepend = "WICHTIGE MITTEILUNG\n\n"\ "Deine Anmeldung ist aktuell nicht vollständig. Bitte fülle umgehend das"\ " Anmeldeformular aus und lasse es Deine*r Jugendleiter*in zukommen! Dieses"\ @@ -62,16 +64,20 @@ def get_content(content, registration_complete=True): def get_unsubscribe_link(member): key = member.generate_key() - return "https://{}/newsletter/unsubscribe?key={}".format(HOST, key) + return prepend_base_url("/newsletter/unsubscribe?key={}".format(key)) def get_echo_link(member): key = member.generate_echo_key() - return "https://{}/members/echo?key={}".format(HOST, key) + return prepend_base_url("/members/echo?key={}".format(key)) def get_mail_confirmation_link(key): - return "https://{}/members/mail/confirm?key={}".format(HOST, key) + return prepend_base_url("/members/mail/confirm?key={}".format(key)) + + +def prepend_base_url(absolutelink): + return "{protocol}://{base}{link}".format(protocol=PROTOCOL, base=BASE_URL, link=absolutelink) mail_root = os.environ.get('EMAIL_SENDING_ADDRESS', 'christian@localhost') diff --git a/jdav_web/members/locale/de/LC_MESSAGES/django.po b/jdav_web/members/locale/de/LC_MESSAGES/django.po index 284d1b4..536c394 100644 --- a/jdav_web/members/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/members/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-10-03 23:57+0200\n" +"POT-Creation-Date: 2022-10-06 11:38+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,7 +18,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: members/admin.py:33 members/models.py:88 +#: members/admin.py:33 members/models.py:89 msgid "Registration complete" msgstr "Anmeldung vollständig" @@ -53,7 +53,7 @@ msgstr "Aktivität" #: members/admin.py:190 msgid "Successfully requested mail confirmation from selected registrations." -msgstr "Aufforderung zur Bestätigung der Email Adresse versendet" +msgstr "Aufforderung zur Bestätigung der Email Adresse versendet." #: members/admin.py:191 msgid "Request mail confirmation from selected registrations" @@ -104,242 +104,247 @@ msgstr "Hinweise für Jugendleiter erstellen" msgid "Generate list for LJP" msgstr "LJP Liste erstellen" -#: members/apps.py:7 members/models.py:240 +#: members/apps.py:7 members/models.py:256 msgid "members" msgstr "Teilnehmer" -#: members/models.py:27 +#: members/models.py:28 msgid "Name" msgstr "Name" -#: members/models.py:28 +#: members/models.py:29 msgid "Description" msgstr "Beschreibung" -#: members/models.py:34 members/models.py:285 members/models.py:364 +#: members/models.py:35 members/models.py:301 members/models.py:380 #: members/templates/members/change_member.html:17 msgid "Activity" msgstr "Aktivität" -#: members/models.py:35 +#: members/models.py:36 msgid "Activities" msgstr "Aktivitäten" -#: members/models.py:43 +#: members/models.py:44 msgid "name" msgstr "Name" -#: members/models.py:44 +#: members/models.py:45 msgid "lowest year" msgstr "Ab Jahrgang" -#: members/models.py:45 +#: members/models.py:46 msgid "highest year" msgstr "Bis Jahrgang" -#: members/models.py:46 +#: members/models.py:47 msgid "youth leaders" msgstr "Jugendleiter" -#: members/models.py:54 members/models.py:81 +#: members/models.py:55 members/models.py:82 msgid "group" msgstr "Gruppe" -#: members/models.py:55 +#: members/models.py:56 msgid "groups" msgstr "Gruppen" -#: members/models.py:68 +#: members/models.py:69 msgid "prename" msgstr "Vorname" -#: members/models.py:69 +#: members/models.py:70 msgid "last name" msgstr "Nachname" -#: members/models.py:62 +#: members/models.py:71 msgid "street and house number" msgstr "Straße und Hausnummer" -#: members/models.py:71 +#: members/models.py:72 msgid "Postcode" msgstr "PLZ" -#: members/models.py:73 +#: members/models.py:74 msgid "town" msgstr "Stadt" -#: members/models.py:74 +#: members/models.py:75 msgid "phone number" msgstr "Telefonnummer" -#: members/models.py:75 +#: members/models.py:76 msgid "parents phone number" msgstr "Telefonnummer der Eltern" -#: members/models.py:78 +#: members/models.py:79 msgid "Parents' Email" msgstr "Email der Eltern" -#: members/models.py:79 +#: members/models.py:80 msgid "Also send mails to parents" msgstr "Emails auch an Eltern schicken" -#: members/models.py:80 +#: members/models.py:81 msgid "birth date" msgstr "Geburtsdatum" -#: members/models.py:82 +#: members/models.py:83 msgid "receives newsletter" msgstr "Erhält den Newsletter" -#: members/models.py:86 +#: members/models.py:87 msgid "comments" msgstr "Kommentare" -#: members/models.py:87 +#: members/models.py:88 msgid "created" msgstr "erstellt" -#: members/models.py:89 +#: members/models.py:90 msgid "Active" msgstr "Aktiv" -#: members/models.py:90 +#: members/models.py:91 msgid "Not waiting" msgstr "NICHT Warteliste" -#: members/models.py:91 +#: members/models.py:92 msgid "registration form" msgstr "Anmeldeformular" -#: members/models.py:101 +#: members/models.py:102 msgid "Echoed" msgstr "Rückgemeldet" -#: members/models.py:102 +#: members/models.py:103 msgid "Confirmed" msgstr "Bestätigt" -#: members/models.py:103 +#: members/models.py:104 msgid "Email confirmed" msgstr "Emailadresse bestätigt" -#: members/models.py:104 +#: members/models.py:105 msgid "Parents email confirmed" msgstr "Emailadresse der Eltern bestätigt" -#: members/models.py:137 members/models.py:147 -msgid "Email confirmation" -msgstr "Email Bestätigung" +#: members/models.py:138 members/models.py:148 +msgid "Email confirmation needed" +msgstr "Email Bestätigung erforderlich" + +#: members/models.py:176 +#, python-format +msgid "New unconfirmed registration for group %(group)s" +msgstr "Neue unbestätigte Registrierung für Gruppe %(group)s" -#: members/models.py:236 members/models.py:446 +#: members/models.py:252 members/models.py:462 msgid "Group" msgstr "Gruppe" -#: members/models.py:239 +#: members/models.py:255 msgid "member" msgstr "Teilnehmer" -#: members/models.py:270 +#: members/models.py:286 msgid "Unconfirmed registration" msgstr "Unbestätigte Registrierung" -#: members/models.py:271 +#: members/models.py:287 msgid "Unconfirmed registrations" msgstr "Unbestätigte Registrierungen" -#: members/models.py:287 members/models.py:366 +#: members/models.py:303 members/models.py:382 msgid "Place" msgstr "Ort" -#: members/models.py:288 members/models.py:367 +#: members/models.py:304 members/models.py:383 msgid "Destination (optional)" msgstr "Ziel (optional)" -#: members/models.py:290 members/models.py:369 members/models.py:424 -#: members/models.py:442 +#: members/models.py:306 members/models.py:385 members/models.py:440 +#: members/models.py:458 msgid "Date" msgstr "Datum" -#: members/models.py:291 members/models.py:370 +#: members/models.py:307 members/models.py:386 msgid "End (optional)" msgstr "Ende" -#: members/models.py:293 members/models.py:372 +#: members/models.py:309 members/models.py:388 msgid "Groups" msgstr "Gruppen" -#: members/models.py:301 members/models.py:385 +#: members/models.py:317 members/models.py:401 msgid "Categories" msgstr "Kategorien" -#: members/models.py:302 members/models.py:386 +#: members/models.py:318 members/models.py:402 msgid "easy" msgstr "leicht" -#: members/models.py:302 members/models.py:386 +#: members/models.py:318 members/models.py:402 msgid "medium" msgstr "mittel" -#: members/models.py:302 members/models.py:386 +#: members/models.py:318 members/models.py:402 msgid "hard" msgstr "schwer" -#: members/models.py:311 +#: members/models.py:327 msgid "Memberlist" msgstr "Teilnehmerliste" -#: members/models.py:312 +#: members/models.py:328 msgid "Memberlists" msgstr "Teilnehmerlisten" -#: members/models.py:330 members/models.py:338 members/models.py:346 -#: members/models.py:357 members/models.py:477 members/models.py:484 +#: members/models.py:346 members/models.py:354 members/models.py:362 +#: members/models.py:373 members/models.py:493 members/models.py:500 msgid "Member" msgstr "Teilnehmer" -#: members/models.py:332 members/models.py:351 +#: members/models.py:348 members/models.py:367 msgid "Comment" msgstr "Kommentar" -#: members/models.py:339 members/models.py:358 members/models.py:485 +#: members/models.py:355 members/models.py:374 members/models.py:501 msgid "Members" msgstr "Teilnehmer" -#: members/models.py:423 +#: members/models.py:439 msgid "Title" msgstr "Titel" -#: members/models.py:443 +#: members/models.py:459 msgid "Location" msgstr "Ort" -#: members/models.py:444 +#: members/models.py:460 msgid "Topic" msgstr "Thema" -#: members/models.py:468 +#: members/models.py:484 msgid "Jugendleiter" msgstr "Jugendleiter" -#: members/models.py:471 +#: members/models.py:487 msgid "Klettertreff" msgstr "Klettertreff" -#: members/models.py:472 +#: members/models.py:488 msgid "Klettertreffs" msgstr "Klettertreffs" -#: members/models.py:490 +#: members/models.py:506 msgid "Password" msgstr "Passwort" -#: members/models.py:493 +#: members/models.py:509 msgid "registration password" msgstr "Registrierungspassort" -#: members/models.py:494 +#: members/models.py:510 msgid "registration passwords" msgstr "Registrierungspasswörter" @@ -467,8 +472,9 @@ msgstr "Ich bin Mitglied des DAV Ludwigsburg." msgid "" "I agree that my data is stored and processed on the server of the JDAV " "Ludwigsburg." -msgstr "Ich bin einverstanden, dass meine Daten auf dem Server der JDAV " -"Ludwigsburg gespeichert und verarbeitet werden." +msgstr "" +"Ich bin einverstanden, dass meine Daten auf dem Server der JDAV Ludwigsburg " +"gespeichert und verarbeitet werden." #: members/templates/members/register_password.html:13 msgid "" diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index f6fc20d..5aca41b 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -10,7 +10,8 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelatio from django.contrib.contenttypes.models import ContentType from utils import RestrictedFileField import os -from mailer.mailutils import send as send_mail, mail_root, get_mail_confirmation_link +from mailer.mailutils import send as send_mail, mail_root, get_mail_confirmation_link,\ + prepend_base_url from django.contrib.auth.models import User from dateutil.relativedelta import relativedelta @@ -134,7 +135,7 @@ class Member(models.Model): self.confirmed_mail = False self.confirm_mail_key = uuid.uuid4().hex group = ", ".join([g.name for g in self.group.all()]) - send_mail(_('Email confirmation'), + send_mail(_('Email confirmation needed'), CONFIRM_MAIL_TEXT.format(name=self.prename, group=group, link=get_mail_confirmation_link(self.confirm_mail_key), @@ -144,7 +145,7 @@ class Member(models.Model): if self.email_parents: self.confirmed_mail_parents = False self.confirm_mail_parents_key = uuid.uuid4().hex - send_mail(_('Email confirmation'), + send_mail(_('Email confirmation needed'), CONFIRM_MAIL_TEXT.format(name=self.prename, group=group, link=get_mail_confirmation_link(self.confirm_mail_parents_key), @@ -156,14 +157,29 @@ class Member(models.Model): self.save() def confirm_mail(self, key): + parents = False + email = None if self.confirm_mail_key == key: self.confirm_mail_key, self.confirmed_mail = "", True - self.save() - return (self.email, False) + email, parents = self.email, False elif self.confirm_mail_parents_key == key: self.confirm_mail_parents_key, self.confirmed_mail_parents = "", True - self.save() - return (self.email_parents, True) + email, parents = self.email_parents, True + self.save() + if self.confirmed_mail_parents and self.confirmed_mail and not self.confirmed: + group = ", ".join([g.name for g in self.group.all()]) + # notify jugendleiters of group of registration + jls = [jl for group in self.group.all() for jl in group.leiters.all()] + for jl in jls: + link = prepend_base_url(reverse('admin:members_memberunconfirmedproxy_change', + args=[str(self.id)])) + send_mail(_('New unconfirmed registration for group %(group)s') % {'group': group}, + NEW_UNCONFIRMED_REGISTRATION.format(name=jl.prename, + group=group, + link=link), + mail_root, + jl.email) + return (email, parents) def confirm(self): if not self.confirmed_mail or not self.confirmed_mail_parents: @@ -591,5 +607,16 @@ folgenden Link: {link} -Viele Grüße, +Viele Grüße Deine JDAV Ludwigsburg""" + +NEW_UNCONFIRMED_REGISTRATION = """Hallo {name}, + +für deine Gruppe {group} liegt eine neue unbestätigte Reservierung vor. Die Person hat bereits ihre +E-Mailadressen bestätigt. Bitte prüfe die Registrierung eingehend und bestätige falls möglich. Zu +der Registrierung kommst du hier: + +{link} + +Viele Grüße +Dein KOMPASS""" diff --git a/jdav_web/members/views.py b/jdav_web/members/views.py index 4274e66..c36b4b4 100644 --- a/jdav_web/members/views.py +++ b/jdav_web/members/views.py @@ -2,7 +2,7 @@ from django.shortcuts import render from django.utils.translation import gettext_lazy as _ from django.http import HttpResponseRedirect from django.forms import ModelForm, TextInput, DateInput -from members.models import Member, RegistrationPassword +from members.models import Member, RegistrationPassword, MemberUnconfirmedProxy from django.urls import reverse from django.utils import timezone @@ -137,7 +137,8 @@ def register(request): def confirm_mail(request): if request.method == 'GET' and 'key' in request.GET: key = request.GET['key'] - res = Member.objects.filter(confirm_mail_key=key) | Member.objects.filter(confirm_mail_parents_key=key) + res = MemberUnconfirmedProxy.objects.filter(confirm_mail_key=key) \ + | MemberUnconfirmedProxy.objects.filter(confirm_mail_parents_key=key) if len(res) != 1: return render_mail_confirmation_invalid(request) member = res[0]