Notification emails #80
@ -26,7 +26,15 @@ class UserAdmin(auth_admin.UserAdmin):
|
||||
(None, {'fields': ('username', 'password')}),
|
||||
(
|
||||
_('Personal info'),
|
||||
{'fields': ('full_name', 'image', 'email', 'badges')},
|
||||
{
|
||||
'fields': (
|
||||
'full_name',
|
||||
'image',
|
||||
'email',
|
||||
'badges',
|
||||
'is_subscribed_to_notification_emails',
|
||||
)
|
||||
},
|
||||
),
|
||||
(
|
||||
_('Permissions'),
|
||||
|
5
users/forms.py
Normal file
5
users/forms.py
Normal file
@ -0,0 +1,5 @@
|
||||
from django import forms
|
||||
|
||||
|
||||
class SubscribeNotificationEmailsForm(forms.Form):
|
||||
subscribe = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
@ -25,7 +25,11 @@ class Command(BaseCommand):
|
||||
to_send = []
|
||||
for n in batch:
|
||||
n.processed_by_mailer_at = timezone.now()
|
||||
# TODO check some form of recipient.is_subscribed(n):
|
||||
if not recipient.is_subscribed_to_notification_emails:
|
||||
continue
|
||||
# check that email is confirmed to avoid spamming unsuspecting email owners
|
||||
if recipient.confirmed_email_at is None:
|
||||
continue
|
||||
n.sent = True
|
||||
to_send.append(n)
|
||||
# first mark as processed, then send: avoid spamming in case of a crash-loop
|
||||
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.11 on 2024-04-15 12:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0002_moderators_group'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='is_subscribed_to_notification_emails',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
@ -36,6 +36,7 @@ class User(TrackChangesMixin, AbstractUser):
|
||||
'confirmed_email_at',
|
||||
'full_name',
|
||||
'email',
|
||||
'is_subscribed_to_notification_emails',
|
||||
}
|
||||
|
||||
class Meta:
|
||||
@ -49,6 +50,8 @@ class User(TrackChangesMixin, AbstractUser):
|
||||
date_deletion_requested = models.DateTimeField(null=True, blank=True)
|
||||
confirmed_email_at = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
is_subscribed_to_notification_emails = models.BooleanField(null=False, default=True)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'{self.full_name or self.username}'
|
||||
|
||||
|
@ -117,4 +117,25 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="mb-3 mt-5">Notifications</h1>
|
||||
<div class="box settings">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4">
|
||||
<form action="{% url 'users:subscribe-notification-emails' %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ subscribe_notification_emails_form }}
|
||||
{% if user.is_subscribed_to_notification_emails %}
|
||||
You are subscribed to notification emails.
|
||||
<button class="btn" type="submit">Unsubscribe</button>
|
||||
{% if not user.confirmed_email_at %}
|
||||
<p class="helptext text-warning">Your need to confirm your email to receive notification emails.</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
You are not subscribed to notification emails.
|
||||
<button class="btn" type="submit">Subscribe</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock settings %}
|
||||
|
@ -11,6 +11,11 @@ urlpatterns = [
|
||||
include(
|
||||
[
|
||||
path('profile/', settings.ProfileView.as_view(), name='my-profile'),
|
||||
path(
|
||||
'profile/subscribe-notification-emails/',
|
||||
settings.SubscribeNotificationEmailsView.as_view(),
|
||||
name='subscribe-notification-emails',
|
||||
),
|
||||
path('delete/', settings.DeleteView.as_view(), name='my-profile-delete'),
|
||||
]
|
||||
),
|
||||
|
@ -1,7 +1,11 @@
|
||||
"""User profile pages."""
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import TemplateView
|
||||
from django.views.generic.edit import FormView
|
||||
|
||||
from users.forms import SubscribeNotificationEmailsForm
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -11,8 +15,25 @@ class ProfileView(LoginRequiredMixin, TemplateView):
|
||||
|
||||
template_name = 'users/settings/profile.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['subscribe_notification_emails_form'] = SubscribeNotificationEmailsForm(
|
||||
{'subscribe': not self.request.user.is_subscribed_to_notification_emails},
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class DeleteView(LoginRequiredMixin, TemplateView):
|
||||
"""Template view where account deletion can be requested."""
|
||||
|
||||
template_name = 'users/settings/delete.html'
|
||||
|
||||
|
||||
class SubscribeNotificationEmailsView(LoginRequiredMixin, FormView):
|
||||
form_class = SubscribeNotificationEmailsForm
|
||||
success_url = reverse_lazy('users:my-profile')
|
||||
|
||||
def form_valid(self, form):
|
||||
self.request.user.is_subscribed_to_notification_emails = form.cleaned_data['subscribe']
|
||||
self.request.user.save(update_fields={'is_subscribed_to_notification_emails'})
|
||||
return super().form_valid(form)
|
||||
|
Loading…
Reference in New Issue
Block a user