From 8f51c6c48ed2533e90a64bc474af9eccf4eeca35 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 17:13:43 +0100 Subject: [PATCH 01/18] add: added mailfeed-app for use under eureka --- nablapps/mailfeed/models.py | 17 +++++++ nablapps/mailfeed/urls.py | 25 ++++++++++ nablapps/mailfeed/views.py | 97 +++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 nablapps/mailfeed/models.py create mode 100644 nablapps/mailfeed/urls.py create mode 100644 nablapps/mailfeed/views.py diff --git a/nablapps/mailfeed/models.py b/nablapps/mailfeed/models.py new file mode 100644 index 00000000..4f5f014c --- /dev/null +++ b/nablapps/mailfeed/models.py @@ -0,0 +1,17 @@ +from django.db import models + + +class MailFeed(models.Model): + name = models.CharField(max_length=40, blank=False, null=False) + created = models.DateTimeField(auto_now=True, verbose_name="Opprettet") + + def get_email_list(self): + subscription_list = Subscription.objects.filter(mailfeed=self) + email_list = [sub.email for sub in subscription_list] + return email_list + + +class Subscription(models.Model): + mailfeed = models.ForeignKey(MailFeed, on_delete=models.CASCADE) + email = models.EmailField(blank=False, null=False) + created = models.DateTimeField(auto_now=True, verbose_name="Opprettet") diff --git a/nablapps/mailfeed/urls.py b/nablapps/mailfeed/urls.py new file mode 100644 index 00000000..c70d3256 --- /dev/null +++ b/nablapps/mailfeed/urls.py @@ -0,0 +1,25 @@ +from django.urls import path + +from .views import ( + CreateMailFeedView, + MailFeedDetailView, + MailFeedListView, + SubscribeView, +) + +urlpatterns = [ + path("", MailFeedListView.as_view(), name="mailfeed-list"), + path( + "detail//", + MailFeedDetailView.as_view(), + name="mailfeed-detail", + ), + path( + "create-mailfeed/", CreateMailFeedView.as_view(), name="create-mailfeed" + ), + path( + "subscribe//", + SubscribeView.as_view(), + name="subscribe-mailfeed", + ), +] diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py new file mode 100644 index 00000000..536e8858 --- /dev/null +++ b/nablapps/mailfeed/views.py @@ -0,0 +1,97 @@ +from .models import MailFeed, Subscription + +from django.core.mail import BadHeaderError, send_mail +from django.contrib.auth.mixins import PermissionRequiredMixin +from django.core.mail import BadHeaderError, send_mail +from django.http import HttpResponse +from django.shortcuts import redirect, render +from django.urls import reverse +from django.views import View +from django.views.generic import DetailView, ListView + +from .forms import SubscribeForm, MailFeedForm, EmailForm + + +class MailFeedListView(PermissionRequiredMixin, ListView): + permission_required = "mailfeed.generate_feed" + model = MailFeed + template_name = "mailfeed/mailfeed_list.html" + paginate_by = 100 + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + return context + + +class CreateMailFeedView(PermissionRequiredMixin, View): + permission_required = "mailfeed.generate_feed" + + def get(self, request): + mailfeed_form = MailFeedForm() + context = {"mailfeed_form": mailfeed_form} + return render(request, "mailfeed/create_mailfeed.html", context) + + def post(self, request): + mailfeed_form = MailFeedForm(request.POST) + if mailfeed_form.is_valid(): + mailfeed_name = mailfeed_form.get_name() + + mailfeed = MailFeed.objects.create(name=mailfeed_name) + mailfeed.save() + return redirect(reverse("mailfeed-list")) + + +class SubscribeView(View): + def get(self, request, mailfeed_id): + subscribe_form = SubscribeForm() + context = {"subscribe_form": subscribe_form} + mailfeed = MailFeed.objects.get(pk=mailfeed_id) + context["mailfeed"] = mailfeed + return render(request, "mailfeed/subscribe_mailfeed.html", context) + + def post(self, request, mailfeed_id): + mailfeed = MailFeed.objects.get(pk=mailfeed_id) + subscribe_form = SubscribeForm(request.POST) + if subscribe_form.is_valid(): + email = subscribe_form.get_email() + subscription = Subscription.objects.create(mailfeed=mailfeed, email=email) + subscription.save() + return HttpResponse("Mailadresse registrert!") + # TODO Det ser ut som ved ugyldig epostadresse kommer vi her. Utdyp feilmeldingen. + return HttpResponse("Noe gikk galt! Prøv igjen senere.") + + +class MailFeedDetailView(DetailView, PermissionRequiredMixin): + permission_required = "mailfeed.generate_feed" + + def get(self, request, mailfeed_id): + email_form = EmailForm() + context = {"email_form": email_form} + mailfeed = MailFeed.objects.get(pk=mailfeed_id) + context["mailfeed"] = mailfeed + email_list = mailfeed.get_email_list() + context["email_list"] = email_list + return render(request, "mailfeed/mailfeed_detail.html", context) + + def post(self, request, mailfeed_id): + email_form = EmailForm(request.POST) + mailfeed = MailFeed.objects.get(pk=mailfeed_id) + email_list = mailfeed.get_email_list() + if not email_form.is_valid(): + return HttpResponse("Oops! Noe gikk galt.") + + subject = email_form.get_subject() + content = email_form.get_content() + for email in email_list: + try: + send_mail( + subject, + content, + None, + [email], + fail_silently=False, + ) + except BadHeaderError: + return HttpResponse("Invalid header found") + + return redirect(reverse("mailfeed-detail", kwargs={"mailfeed_id": mailfeed_id})) From b4b10ce82623cd848709d645c09b1325982aefaf Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 17:14:03 +0100 Subject: [PATCH 02/18] add: added html-pages --- .../templates/mailfeed/create_mailfeed.html | 15 +++++ .../templates/mailfeed/mailfeed_detail.html | 55 +++++++++++++++++++ .../templates/mailfeed/mailfeed_list.html | 15 +++++ .../mailfeed/subscribe_mailfeed.html | 16 ++++++ 4 files changed, 101 insertions(+) create mode 100644 nablapps/mailfeed/templates/mailfeed/create_mailfeed.html create mode 100644 nablapps/mailfeed/templates/mailfeed/mailfeed_detail.html create mode 100644 nablapps/mailfeed/templates/mailfeed/mailfeed_list.html create mode 100644 nablapps/mailfeed/templates/mailfeed/subscribe_mailfeed.html diff --git a/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html b/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html new file mode 100644 index 00000000..c2c4d354 --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block content %} +

Opprett MailFeed

+ + +
+ {% csrf_token %} +

Navn:

+ {{ mailfeed_form.name_field }} +
+ +
+ +{% endblock %} diff --git a/nablapps/mailfeed/templates/mailfeed/mailfeed_detail.html b/nablapps/mailfeed/templates/mailfeed/mailfeed_detail.html new file mode 100644 index 00000000..ff4cc82b --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/mailfeed_detail.html @@ -0,0 +1,55 @@ +{% extends "base.html" %} + +{% block content %} + + + +

Administrerer {{ mailfeed.name }}

+Tilbake til listen over MailFeedene +Abonner på denne feeden +

+
+

+

Generer og send ny mail:

+

+ Når du trykker "send" sendes det ut en mail til alle på listen +

+
+ {% csrf_token %} + Emne +
+ {{ email_form.subject_field }} +
+ Innhold +
+ {{ email_form.content_field }} +
+ +
+ +

Abonnenter

+
+

Epost:

+
+{% for email in email_list %} +
+

{{ email }}

+
+{% endfor %} + + +{% endblock %} \ No newline at end of file diff --git a/nablapps/mailfeed/templates/mailfeed/mailfeed_list.html b/nablapps/mailfeed/templates/mailfeed/mailfeed_list.html new file mode 100644 index 00000000..76f1f433 --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/mailfeed_list.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block content %} +

Administrer Mailfeeder

+ +Opprett ny Mailfeed + +

Mailfeeder

+ + +{% endblock %} diff --git a/nablapps/mailfeed/templates/mailfeed/subscribe_mailfeed.html b/nablapps/mailfeed/templates/mailfeed/subscribe_mailfeed.html new file mode 100644 index 00000000..9d9690c5 --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/subscribe_mailfeed.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} +

Abonner på {{ mailfeed.name }}

+ + +
+ {% csrf_token %} +

Email

+ {{ subscribe_form.email_field }} +
+
+ +
+ +{% endblock %} \ No newline at end of file From b6fe0015d6edc36b4b089b5283c3337958d680ce Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 17:14:52 +0100 Subject: [PATCH 03/18] add: registered app in base and added forms --- nablapps/mailfeed/admin.py | 7 +++++++ nablapps/mailfeed/apps.py | 5 +++++ nablapps/mailfeed/forms.py | 34 ++++++++++++++++++++++++++++++++++ nablapps/mailfeed/tests.py | 3 +++ nablaweb/settings/base.py | 1 + nablaweb/urls.py | 1 + 6 files changed, 51 insertions(+) create mode 100644 nablapps/mailfeed/admin.py create mode 100644 nablapps/mailfeed/apps.py create mode 100644 nablapps/mailfeed/forms.py create mode 100644 nablapps/mailfeed/tests.py diff --git a/nablapps/mailfeed/admin.py b/nablapps/mailfeed/admin.py new file mode 100644 index 00000000..a5fb304d --- /dev/null +++ b/nablapps/mailfeed/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +# Register your models here. +from .models import Subscription, MailFeed + +admin.site.register(Subscription) +admin.site.register(MailFeed) diff --git a/nablapps/mailfeed/apps.py b/nablapps/mailfeed/apps.py new file mode 100644 index 00000000..3187e2d8 --- /dev/null +++ b/nablapps/mailfeed/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class MailfeedConfig(AppConfig): + name = 'nablapps.mailfeed' diff --git a/nablapps/mailfeed/forms.py b/nablapps/mailfeed/forms.py new file mode 100644 index 00000000..7339e3ef --- /dev/null +++ b/nablapps/mailfeed/forms.py @@ -0,0 +1,34 @@ +from django import forms + + +class MailFeedForm(forms.Form): + name_field = forms.CharField(required=True) + + def get_name(self): + cd = self.cleaned_data + name = cd["name_field"] + return name + + +class SubscribeForm(forms.Form): + email_field = forms.EmailField(widget=forms.EmailInput) + + def get_email(self): + cd = self.cleaned_data + email = cd["email_field"] + return email + + +class EmailForm(forms.Form): + subject_field = forms.CharField(max_length=80) + content_field = forms.CharField(required=True, widget=forms.Textarea) + + def get_subject(self): + cd = self.cleaned_data + subject = cd["subject_field"] + return subject + + def get_content(self): + cd = self.cleaned_data + content = cd["content_field"] + return content diff --git a/nablapps/mailfeed/tests.py b/nablapps/mailfeed/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/nablapps/mailfeed/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/nablaweb/settings/base.py b/nablaweb/settings/base.py index ed57a6be..22e28b85 100644 --- a/nablaweb/settings/base.py +++ b/nablaweb/settings/base.py @@ -109,6 +109,7 @@ "nablapps.interactive", "nablapps.jobs", "nablapps.meeting_records", + "nablapps.mailfeed", "nablapps.nabladet", "nablapps.nablaforum", "nablapps.nablashop", diff --git a/nablaweb/urls.py b/nablaweb/urls.py index afacdab4..a1709ea8 100644 --- a/nablaweb/urls.py +++ b/nablaweb/urls.py @@ -52,6 +52,7 @@ path("poll/", include("nablapps.poll.urls")), path("referater/", include("nablapps.meeting_records.urls")), path("qrTickets/", include("nablapps.qrTickets.urls")), + path("mailfeed/", include("nablapps.mailfeed.urls")), path("stem/", include("nablapps.vote.urls")), path( "search/", From c962b2cb82fcc614186323e23f2ea85d82befe9b Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 17:15:26 +0100 Subject: [PATCH 04/18] add: autocreated files --- nablapps/mailfeed/__init__.py | 0 nablapps/mailfeed/migrations/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 nablapps/mailfeed/__init__.py create mode 100644 nablapps/mailfeed/migrations/__init__.py diff --git a/nablapps/mailfeed/__init__.py b/nablapps/mailfeed/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/nablapps/mailfeed/migrations/__init__.py b/nablapps/mailfeed/migrations/__init__.py new file mode 100644 index 00000000..e69de29b From 5fb727c4f42c9797681ac5f743b4ceba354bb0e7 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:25:24 +0100 Subject: [PATCH 05/18] improved error-messages --- nablapps/mailfeed/templates/mailfeed/invalid_email.html | 9 +++++++++ nablapps/mailfeed/templates/mailfeed/msg.html | 7 +++++++ 2 files changed, 16 insertions(+) create mode 100644 nablapps/mailfeed/templates/mailfeed/invalid_email.html create mode 100644 nablapps/mailfeed/templates/mailfeed/msg.html diff --git a/nablapps/mailfeed/templates/mailfeed/invalid_email.html b/nablapps/mailfeed/templates/mailfeed/invalid_email.html new file mode 100644 index 00000000..06edfe76 --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/invalid_email.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% block content %} +

Ugyldig mailadresse

+

+
+

+Prøv igjen +{% endblock %} \ No newline at end of file diff --git a/nablapps/mailfeed/templates/mailfeed/msg.html b/nablapps/mailfeed/templates/mailfeed/msg.html new file mode 100644 index 00000000..3b1a59de --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/msg.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +

{{ msg }}

+ + +{% endblock %} \ No newline at end of file From eea04b7181a1929b22b9449c6218c4f65f287a41 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:25:55 +0100 Subject: [PATCH 06/18] fix: css on button --- nablapps/mailfeed/templates/mailfeed/create_mailfeed.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html b/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html index c2c4d354..eb6fac24 100644 --- a/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html +++ b/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block content %} -

Opprett MailFeed

+

Opprett en mailfeed

@@ -9,7 +9,7 @@

Opprett MailFeed

Navn:

{{ mailfeed_form.name_field }}
- +
-{% endblock %} +{% endblock %} \ No newline at end of file From b1f4f70491f6f85f5741832606b9f961316483e4 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:26:47 +0100 Subject: [PATCH 07/18] fix: removed duplicate emails bug in same feed --- nablapps/mailfeed/views.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py index 536e8858..258f7dc1 100644 --- a/nablapps/mailfeed/views.py +++ b/nablapps/mailfeed/views.py @@ -54,14 +54,24 @@ def post(self, request, mailfeed_id): subscribe_form = SubscribeForm(request.POST) if subscribe_form.is_valid(): email = subscribe_form.get_email() - subscription = Subscription.objects.create(mailfeed=mailfeed, email=email) - subscription.save() - return HttpResponse("Mailadresse registrert!") - # TODO Det ser ut som ved ugyldig epostadresse kommer vi her. Utdyp feilmeldingen. - return HttpResponse("Noe gikk galt! Prøv igjen senere.") + if Subscription.objects.filter(email=email).exists(): + return render( + request, + "mailfeed/msg.html", + {"msg": "Denne eposten er allerede registrert fra før."}, + ) + else: + subscription = Subscription.objects.create( + mailfeed=mailfeed, email=email + ) + subscription.save() + return render( + request, "mailfeed/msg.html", {"msg": "Mailadressen registrert!"} + ) + return render(request, "mailfeed/invalid_email.html", {"mailfeed": mailfeed}) -class MailFeedDetailView(DetailView, PermissionRequiredMixin): +class MailFeedDetailView(PermissionRequiredMixin, DetailView): permission_required = "mailfeed.generate_feed" def get(self, request, mailfeed_id): From 0474bc29fa321f0dbf21a7b17661648a670e1bbd Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:26:58 +0100 Subject: [PATCH 08/18] migration --- nablapps/mailfeed/migrations/0001_initial.py | 32 +++++++++++++++++++ .../migrations/0002_auto_20240109_1653.py | 23 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 nablapps/mailfeed/migrations/0001_initial.py create mode 100644 nablapps/mailfeed/migrations/0002_auto_20240109_1653.py diff --git a/nablapps/mailfeed/migrations/0001_initial.py b/nablapps/mailfeed/migrations/0001_initial.py new file mode 100644 index 00000000..254f533f --- /dev/null +++ b/nablapps/mailfeed/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# Generated by Django 3.2.22 on 2024-01-08 23:34 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='MailFeed', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_created=True, verbose_name='Opprettet')), + ('name', models.CharField(max_length=40)), + ], + ), + migrations.CreateModel( + name='Subscription', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_created=True, verbose_name='Opprettet')), + ('email', models.EmailField(max_length=254)), + ('mailfeed', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mailfeed.mailfeed')), + ], + ), + ] diff --git a/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py b/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py new file mode 100644 index 00000000..a7eb8b31 --- /dev/null +++ b/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.22 on 2024-01-09 16:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailfeed', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='mailfeed', + name='created', + field=models.DateTimeField(auto_now=True, verbose_name='Opprettet'), + ), + migrations.AlterField( + model_name='subscription', + name='created', + field=models.DateTimeField(auto_now=True, verbose_name='Opprettet'), + ), + ] From d0f2ba60d4f58d51218ebec20f76c5d3a13b62df Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:37:08 +0100 Subject: [PATCH 09/18] add: added back button when creating mailfeeds --- nablapps/mailfeed/templates/mailfeed/create_mailfeed.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html b/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html index eb6fac24..dcb51715 100644 --- a/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html +++ b/nablapps/mailfeed/templates/mailfeed/create_mailfeed.html @@ -3,7 +3,10 @@ {% block content %}

Opprett en mailfeed

- +Tilbake +

+
+

{% csrf_token %}

Navn:

From 45e04fcaa94a88483fd76498c9b272cdaa5e0a0e Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:38:18 +0100 Subject: [PATCH 10/18] fix: fixed permissions to edit mailfeeds --- nablapps/mailfeed/admin.py | 4 ++-- nablapps/mailfeed/models.py | 9 +++++++-- nablapps/mailfeed/views.py | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/nablapps/mailfeed/admin.py b/nablapps/mailfeed/admin.py index a5fb304d..3b556bf9 100644 --- a/nablapps/mailfeed/admin.py +++ b/nablapps/mailfeed/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin # Register your models here. -from .models import Subscription, MailFeed +from .models import Subscription, Mailfeed admin.site.register(Subscription) -admin.site.register(MailFeed) +admin.site.register(Mailfeed) diff --git a/nablapps/mailfeed/models.py b/nablapps/mailfeed/models.py index 4f5f014c..feeccda9 100644 --- a/nablapps/mailfeed/models.py +++ b/nablapps/mailfeed/models.py @@ -1,7 +1,7 @@ from django.db import models -class MailFeed(models.Model): +class Mailfeed(models.Model): name = models.CharField(max_length=40, blank=False, null=False) created = models.DateTimeField(auto_now=True, verbose_name="Opprettet") @@ -10,8 +10,13 @@ def get_email_list(self): email_list = [sub.email for sub in subscription_list] return email_list + class Meta: + permissions = [ + ("generate_mailfeeds", "can generate mailfeeds"), + ] + class Subscription(models.Model): - mailfeed = models.ForeignKey(MailFeed, on_delete=models.CASCADE) + mailfeed = models.ForeignKey(Mailfeed, on_delete=models.CASCADE) email = models.EmailField(blank=False, null=False) created = models.DateTimeField(auto_now=True, verbose_name="Opprettet") diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py index 258f7dc1..cd10d731 100644 --- a/nablapps/mailfeed/views.py +++ b/nablapps/mailfeed/views.py @@ -1,4 +1,4 @@ -from .models import MailFeed, Subscription +from .models import Mailfeed, Subscription from django.core.mail import BadHeaderError, send_mail from django.contrib.auth.mixins import PermissionRequiredMixin @@ -13,8 +13,8 @@ class MailFeedListView(PermissionRequiredMixin, ListView): - permission_required = "mailfeed.generate_feed" - model = MailFeed + permission_required = "Mailfeed.generate_mailfeeds" + model = Mailfeed template_name = "mailfeed/mailfeed_list.html" paginate_by = 100 @@ -24,7 +24,7 @@ def get_context_data(self, **kwargs): class CreateMailFeedView(PermissionRequiredMixin, View): - permission_required = "mailfeed.generate_feed" + permission_required = "Mailfeed.generate_mailfeeds" def get(self, request): mailfeed_form = MailFeedForm() @@ -36,7 +36,7 @@ def post(self, request): if mailfeed_form.is_valid(): mailfeed_name = mailfeed_form.get_name() - mailfeed = MailFeed.objects.create(name=mailfeed_name) + mailfeed = Mailfeed.objects.create(name=mailfeed_name) mailfeed.save() return redirect(reverse("mailfeed-list")) @@ -45,12 +45,12 @@ class SubscribeView(View): def get(self, request, mailfeed_id): subscribe_form = SubscribeForm() context = {"subscribe_form": subscribe_form} - mailfeed = MailFeed.objects.get(pk=mailfeed_id) + mailfeed = Mailfeed.objects.get(pk=mailfeed_id) context["mailfeed"] = mailfeed return render(request, "mailfeed/subscribe_mailfeed.html", context) def post(self, request, mailfeed_id): - mailfeed = MailFeed.objects.get(pk=mailfeed_id) + mailfeed = Mailfeed.objects.get(pk=mailfeed_id) subscribe_form = SubscribeForm(request.POST) if subscribe_form.is_valid(): email = subscribe_form.get_email() @@ -72,12 +72,12 @@ def post(self, request, mailfeed_id): class MailFeedDetailView(PermissionRequiredMixin, DetailView): - permission_required = "mailfeed.generate_feed" + permission_required = "Mailfeed.generate_mailfeeds" def get(self, request, mailfeed_id): email_form = EmailForm() context = {"email_form": email_form} - mailfeed = MailFeed.objects.get(pk=mailfeed_id) + mailfeed = Mailfeed.objects.get(pk=mailfeed_id) context["mailfeed"] = mailfeed email_list = mailfeed.get_email_list() context["email_list"] = email_list @@ -85,7 +85,7 @@ def get(self, request, mailfeed_id): def post(self, request, mailfeed_id): email_form = EmailForm(request.POST) - mailfeed = MailFeed.objects.get(pk=mailfeed_id) + mailfeed = Mailfeed.objects.get(pk=mailfeed_id) email_list = mailfeed.get_email_list() if not email_form.is_valid(): return HttpResponse("Oops! Noe gikk galt.") From cfe85621b5a8f96c4e607bb342638139c0e0cc94 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:38:42 +0100 Subject: [PATCH 11/18] permission to edit mailfeeds migration --- .../migrations/0003_alter_mailfeed_options.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py diff --git a/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py b/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py new file mode 100644 index 00000000..66006269 --- /dev/null +++ b/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.22 on 2024-01-09 18:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailfeed', '0002_auto_20240109_1653'), + ] + + operations = [ + migrations.AlterModelOptions( + name='mailfeed', + options={'permissions': [('generate_mailfeeds', 'can generate mailfeeds')]}, + ), + ] From 52e296abc1b799c458c65c9f02d973b29c7fe194 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:51:03 +0100 Subject: [PATCH 12/18] updated Pipfile.lock --- Pipfile.lock | 838 +++++++++++++++++++++++---------------------------- 1 file changed, 383 insertions(+), 455 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 052c4afe..975b1161 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -50,27 +50,27 @@ }, "django": { "hashes": [ - "sha256:83b6d66b06e484807d778263fdc7f9186d4dc1862fcfa6507830446ac6b060ba", - "sha256:c5e7b668025a6e06cad9ba6d4de1fd1a21212acebb51ea34abb400c6e4d33430" + "sha256:82968f3640e29ef4a773af2c28448f5f7a08d001c6ac05b32d02aeee6509508b", + "sha256:d48608d5f62f2c1e260986835db089fa3b79d6f58510881d316b8d88345ae6e1" ], "index": "pypi", - "version": "==3.2.22" + "version": "==3.2.23" }, "django-appconf": { "hashes": [ - "sha256:ae9f864ee1958c815a965ed63b3fba4874eec13de10236ba063a788f9a17389d", - "sha256:be3db0be6c81fa84742000b89a81c016d70ae66a7ccb620cdef592b1f1a6aaa4" + "sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993", + "sha256:cfe87ea827c4ee04b9a70fab90b86d704cb02f2981f89da8423cb0fabf88efbf" ], - "markers": "python_version >= '3.6'", - "version": "==1.0.5" + "markers": "python_version >= '3.7'", + "version": "==1.0.6" }, "django-bootstrap4": { "hashes": [ - "sha256:6b5080a4bce80fa666ac5ce5d4c77ad6fc3c0984d4257a0060d4077f515f62e5", - "sha256:6c895cdda58de1360bf82cc9e31014ad158dad680198ac8366ca33c19efa972f" + "sha256:577df4009adc21c8c65b7bfc3cd074c26072e245c43e6183ee0c6ae01181c263", + "sha256:f7f40ad719c1b20399c804336e56a810abc1dec7ba56257756964c10005916f9" ], "index": "pypi", - "version": "==23.2" + "version": "==23.4" }, "django-braces": { "hashes": [ @@ -145,11 +145,11 @@ }, "django-js-asset": { "hashes": [ - "sha256:36a3a4dd6e9efc895fb127d13126020f6ec1ec9469ad42878d42143f22495d90", - "sha256:be6f69ae5c4865617aa7726c48eddb64089a1e7d4ea7d22a35a3beb8282020f6" + "sha256:0c57a82cae2317e83951d956110ce847f58ff0cdc24e314dbc18b35033917e94", + "sha256:7ef3e858e13d06f10799b56eea62b1e76706f42cf4e709be4e13356bc0ae30d8" ], "markers": "python_version >= '3.8'", - "version": "==2.1.0" + "version": "==2.2.0" }, "django-markdown-deux": { "hashes": [ @@ -230,6 +230,14 @@ "index": "pypi", "version": "==21.2.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e", + "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc" + ], + "markers": "python_version < '3.10'", + "version": "==7.0.1" + }, "markdown": { "hashes": [ "sha256:1fafe3f1ecabfb514a5285fca634a53c1b32a81cb0feb154264d55bf2ff22c17", @@ -240,11 +248,11 @@ }, "markdown2": { "hashes": [ - "sha256:cdba126d90dc3aef6f4070ac342f974d63f415678959329cc7909f96cc235d72", - "sha256:e6105800483783831f5dc54f827aa5b44eb137ecef5a70293d8ecfbb4109ecc6" + "sha256:1bc8692696954d597778e0e25713c14ca56d87992070dedd95c17eddaf709204", + "sha256:98f47591006f0ace0644cbece03fed6f3845513286f6c6e9f8bcf6a575174e2c" ], "markers": "python_version >= '3.5' and python_version < '4'", - "version": "==2.4.10" + "version": "==2.4.12" }, "packaging": { "hashes": [ @@ -256,183 +264,196 @@ }, "pillow": { "hashes": [ - "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff", - "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f", - "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21", - "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635", - "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a", - "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f", - "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1", - "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d", - "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db", - "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849", - "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7", - "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876", - "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3", - "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317", - "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91", - "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d", - "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b", - "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd", - "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed", - "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500", - "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7", - "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a", - "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a", - "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0", - "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf", - "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f", - "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1", - "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088", - "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971", - "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a", - "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205", - "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54", - "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08", - "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21", - "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d", - "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08", - "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e", - "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf", - "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b", - "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145", - "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2", - "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d", - "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d", - "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf", - "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad", - "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d", - "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1", - "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4", - "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2", - "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19", - "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37", - "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4", - "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68", - "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1" + "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8", + "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39", + "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac", + "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869", + "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e", + "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04", + "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9", + "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e", + "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe", + "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef", + "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56", + "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa", + "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f", + "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f", + "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e", + "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a", + "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2", + "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2", + "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5", + "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a", + "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2", + "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213", + "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563", + "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591", + "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c", + "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2", + "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb", + "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757", + "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0", + "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452", + "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad", + "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01", + "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f", + "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5", + "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61", + "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e", + "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b", + "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068", + "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9", + "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588", + "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483", + "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f", + "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67", + "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7", + "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311", + "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6", + "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72", + "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6", + "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129", + "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13", + "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67", + "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c", + "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516", + "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e", + "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e", + "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364", + "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023", + "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1", + "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04", + "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d", + "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a", + "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7", + "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb", + "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4", + "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e", + "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1", + "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48", + "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868" ], "markers": "python_version >= '3.8'", - "version": "==10.0.1" + "version": "==10.2.0" }, "pydantic": { "hashes": [ - "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7", - "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1" + "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a", + "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4" ], "markers": "python_version >= '3.7'", - "version": "==2.4.2" + "version": "==2.5.3" }, "pydantic-core": { "hashes": [ - "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e", - "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33", - "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7", - "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7", - "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea", - "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4", - "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0", - "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7", - "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94", - "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff", - "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82", - "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd", - "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893", - "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e", - "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d", - "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901", - "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9", - "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c", - "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7", - "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891", - "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f", - "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a", - "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9", - "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5", - "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e", - "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a", - "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c", - "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f", - "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514", - "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b", - "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302", - "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096", - "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0", - "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27", - "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884", - "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a", - "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357", - "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430", - "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221", - "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325", - "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4", - "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05", - "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55", - "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875", - "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970", - "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc", - "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6", - "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f", - "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b", - "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d", - "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15", - "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118", - "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee", - "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e", - "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6", - "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208", - "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede", - "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3", - "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e", - "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada", - "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175", - "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a", - "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c", - "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f", - "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58", - "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f", - "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a", - "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a", - "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921", - "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e", - "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904", - "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776", - "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52", - "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf", - "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8", - "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f", - "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b", - "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63", - "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c", - "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f", - "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468", - "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e", - "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab", - "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2", - "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb", - "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb", - "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132", - "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b", - "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607", - "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934", - "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698", - "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e", - "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561", - "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de", - "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b", - "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a", - "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595", - "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402", - "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881", - "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429", - "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5", - "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7", - "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c", - "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531", - "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6", - "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521" + "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556", + "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e", + "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411", + "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245", + "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c", + "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66", + "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd", + "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d", + "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b", + "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06", + "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948", + "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341", + "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0", + "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f", + "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a", + "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2", + "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51", + "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80", + "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8", + "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d", + "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8", + "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb", + "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590", + "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87", + "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534", + "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b", + "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145", + "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba", + "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b", + "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2", + "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e", + "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052", + "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622", + "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab", + "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b", + "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66", + "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e", + "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4", + "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e", + "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec", + "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c", + "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed", + "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937", + "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f", + "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9", + "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4", + "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96", + "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277", + "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23", + "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7", + "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b", + "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91", + "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d", + "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e", + "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1", + "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2", + "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160", + "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9", + "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670", + "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7", + "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c", + "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb", + "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42", + "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d", + "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8", + "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1", + "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6", + "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8", + "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf", + "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e", + "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a", + "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9", + "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1", + "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40", + "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2", + "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d", + "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f", + "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f", + "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af", + "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7", + "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda", + "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a", + "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95", + "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0", + "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60", + "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149", + "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975", + "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4", + "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe", + "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94", + "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03", + "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c", + "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b", + "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a", + "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24", + "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391", + "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c", + "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab", + "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd", + "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786", + "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08", + "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8", + "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6", + "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0", + "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421" ], "markers": "python_version >= '3.7'", - "version": "==2.10.1" + "version": "==2.14.6" }, "pymysql": { "hashes": [ @@ -451,11 +472,11 @@ }, "segno": { "hashes": [ - "sha256:983424b296e62189d70fc73460cd946cf56dcbe82b9bda18c066fc1b24371cdc", - "sha256:b17ace8171aad3987e01bb4aeadf7e0450c40674024c4c57b4da54028e55f1e9" + "sha256:8d3b11098ac6dd93161499544dedbfb187d4459088109b8855ff0bbe98105047", + "sha256:e9c7479e144f750b837f9527fe7492135908b2515586467bc3c893b60a4e4d39" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.5.2" + "markers": "python_version >= '3.5'", + "version": "==1.6.0" }, "six": { "hashes": [ @@ -491,19 +512,19 @@ }, "typing-extensions": { "hashes": [ - "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", - "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" ], "markers": "python_version < '3.11'", - "version": "==4.8.0" + "version": "==4.9.0" }, "wand": { "hashes": [ - "sha256:1b77e25439ace57f665d1ccc6cff2766fad0834005b89ae3e7aaf3ba12b124b0", - "sha256:b661700da9f8f1e931e52726e4fc643a565b9514f5883d41b773e3c37c9fa995" + "sha256:e5dda0ac2204a40c29ef5c4cb310770c95d3d05c37b1379e69c94ea79d7d19c0", + "sha256:f5013484eaf7a20eb22d1821aaefe60b50cc329722372b5f8565d46d4aaafcca" ], "index": "pypi", - "version": "==0.6.11" + "version": "==0.6.13" }, "webencodings": { "hashes": [ @@ -528,52 +549,60 @@ ], "index": "pypi", "version": "==0.8.1 " + }, + "zipp": { + "hashes": [ + "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31", + "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0" + ], + "markers": "python_version >= '3.8'", + "version": "==3.17.0" } }, "develop": { "astroid": { "hashes": [ - "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c", - "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a" + "sha256:4a61cf0a59097c7bb52689b0fd63717cd2a8a14dc9f1eee97b82d814881c8c91", + "sha256:d6e62862355f60e716164082d6b4b041d38e2a8cf1c7cd953ded5108bac8ff5c" ], - "markers": "python_full_version >= '3.7.2'", - "version": "==2.15.8" + "markers": "python_full_version >= '3.8.0'", + "version": "==3.0.2" }, "bandit": { "hashes": [ - "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549", - "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e" + "sha256:36da17c67fc87579a5d20c323c8d0b1643a890a2b93f00b3d1229966624694ff", + "sha256:72ce7bc9741374d96fb2f1c9a8960829885f1243ffde743de70a19cee353e8f3" ], "index": "pypi", - "version": "==1.7.5" + "version": "==1.7.6" }, "black": { "hashes": [ - "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f", - "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7", - "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100", - "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573", - "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d", - "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f", - "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9", - "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300", - "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948", - "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325", - "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9", - "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71", - "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186", - "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f", - "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe", - "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855", - "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80", - "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393", - "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c", - "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204", - "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377", - "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301" + "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50", + "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f", + "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e", + "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec", + "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055", + "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3", + "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5", + "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54", + "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b", + "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e", + "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e", + "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba", + "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea", + "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59", + "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d", + "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0", + "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9", + "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a", + "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e", + "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba", + "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2", + "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2" ], "index": "pypi", - "version": "==23.9.1" + "version": "==23.12.1" }, "cfgv": { "hashes": [ @@ -591,6 +620,14 @@ "markers": "python_version >= '3.7'", "version": "==8.1.7" }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "platform_system == 'Windows'", + "version": "==0.4.6" + }, "dill": { "hashes": [ "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e", @@ -601,10 +638,10 @@ }, "distlib": { "hashes": [ - "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057", - "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8" + "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", + "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64" ], - "version": "==0.3.7" + "version": "==0.3.8" }, "factory-boy": { "hashes": [ @@ -616,19 +653,19 @@ }, "faker": { "hashes": [ - "sha256:5b234b89a9c536a37420f612169b6e58627b823ba1bba2504c0450db3b136620", - "sha256:d86cb3150626bd642c6abd8a64107ddb0b154500252f46a56efe527a50594866" + "sha256:3cd0e04ed7da1bb8037afc40d1127d19e0ac4afac247a1fe1d8dde9b5c6d6e5b", + "sha256:d1b8fe8e8fc96d816294a301741940c2229dcf1f5dd1231805666e4005cc6353" ], "index": "pypi", - "version": "==19.8.0" + "version": "==22.1.0" }, "filelock": { "hashes": [ - "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4", - "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd" + "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", + "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c" ], "markers": "python_version >= '3.8'", - "version": "==3.12.4" + "version": "==3.13.1" }, "flake8": { "hashes": [ @@ -640,27 +677,27 @@ }, "gitdb": { "hashes": [ - "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a", - "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7" + "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", + "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" ], "markers": "python_version >= '3.7'", - "version": "==4.0.10" + "version": "==4.0.11" }, "gitpython": { "hashes": [ - "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33", - "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54" + "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4", + "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a" ], "markers": "python_version >= '3.7'", - "version": "==3.1.37" + "version": "==3.1.40" }, "identify": { "hashes": [ - "sha256:afe67f26ae29bab007ec21b03d4114f41316ab9dd15aa8736a167481e108da54", - "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d" + "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d", + "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34" ], "markers": "python_version >= '3.8'", - "version": "==2.5.30" + "version": "==2.5.33" }, "isort": { "hashes": [ @@ -670,48 +707,6 @@ "index": "pypi", "version": "==5.9.3" }, - "lazy-object-proxy": { - "hashes": [ - "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382", - "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82", - "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9", - "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494", - "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46", - "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30", - "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63", - "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4", - "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae", - "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be", - "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701", - "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd", - "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006", - "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a", - "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586", - "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8", - "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821", - "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07", - "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b", - "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171", - "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b", - "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2", - "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7", - "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4", - "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8", - "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e", - "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f", - "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda", - "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4", - "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e", - "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671", - "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11", - "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", - "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", - "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", - "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.0" - }, "markdown-it-py": { "hashes": [ "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", @@ -762,95 +757,109 @@ }, "pathspec": { "hashes": [ - "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", - "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" + "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", + "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" ], - "markers": "python_version >= '3.7'", - "version": "==0.11.2" + "markers": "python_version >= '3.8'", + "version": "==0.12.1" }, "pbr": { "hashes": [ - "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b", - "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3" + "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda", + "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9" ], "markers": "python_version >= '2.6'", - "version": "==5.11.1" + "version": "==6.0.0" }, "pillow": { "hashes": [ - "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff", - "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f", - "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21", - "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635", - "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a", - "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f", - "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1", - "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d", - "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db", - "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849", - "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7", - "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876", - "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3", - "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317", - "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91", - "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d", - "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b", - "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd", - "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed", - "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500", - "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7", - "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a", - "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a", - "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0", - "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf", - "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f", - "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1", - "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088", - "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971", - "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a", - "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205", - "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54", - "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08", - "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21", - "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d", - "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08", - "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e", - "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf", - "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b", - "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145", - "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2", - "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d", - "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d", - "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf", - "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad", - "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d", - "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1", - "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4", - "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2", - "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19", - "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37", - "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4", - "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68", - "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1" + "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8", + "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39", + "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac", + "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869", + "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e", + "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04", + "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9", + "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e", + "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe", + "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef", + "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56", + "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa", + "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f", + "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f", + "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e", + "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a", + "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2", + "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2", + "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5", + "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a", + "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2", + "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213", + "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563", + "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591", + "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c", + "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2", + "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb", + "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757", + "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0", + "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452", + "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad", + "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01", + "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f", + "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5", + "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61", + "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e", + "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b", + "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068", + "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9", + "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588", + "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483", + "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f", + "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67", + "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7", + "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311", + "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6", + "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72", + "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6", + "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129", + "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13", + "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67", + "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c", + "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516", + "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e", + "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e", + "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364", + "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023", + "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1", + "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04", + "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d", + "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a", + "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7", + "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb", + "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4", + "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e", + "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1", + "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48", + "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868" ], "markers": "python_version >= '3.8'", - "version": "==10.0.1" + "version": "==10.2.0" }, "platformdirs": { "hashes": [ - "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3", - "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e" + "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", + "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420" ], - "markers": "python_version >= '3.7'", - "version": "==3.11.0" + "markers": "python_version >= '3.8'", + "version": "==4.1.0" }, "pre-commit": { "hashes": [ - "sha256:6bbd5129a64cad4c0dfaeeb12cd8f7ea7e15b77028d985341478c8af3c759522", - "sha256:96d529a951f8b677f730a7212442027e8ba53f9b04d217c4c67dc56c393ad945" + "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376", + "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d" ], "index": "pypi", - "version": "==3.4.0" + "version": "==3.6.0" }, "pycodestyle": { "hashes": [ @@ -870,27 +879,27 @@ }, "pygments": { "hashes": [ - "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692", - "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29" + "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", + "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" ], "markers": "python_version >= '3.7'", - "version": "==2.16.1" + "version": "==2.17.2" }, "pylint": { "hashes": [ - "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87", - "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad" + "sha256:58c2398b0301e049609a8429789ec6edf3aabe9b6c5fec916acd18639c16de8b", + "sha256:7a1585285aefc5165db81083c3e06363a27448f6b467b3b0f30dbd0ac1f73810" ], "index": "pypi", - "version": "==2.17.7" + "version": "==3.0.3" }, "pylint-django": { "hashes": [ - "sha256:0ac090d106c62fe33782a1d01bda1610b761bb1c9bf5035ced9d5f23a13d8591", - "sha256:56b12b6adf56d548412445bd35483034394a1a94901c3f8571980a13882299d5" + "sha256:2f339e4bf55776958283395c5139c37700c91bd5ef1d8251ef6ac88b5abbba9b", + "sha256:5abd5c2228e0e5e2a4cb6d0b4fc1d1cef1e773d0be911412f4dd4fc1a1a440b7" ], "index": "pypi", - "version": "==2.5.3" + "version": "==2.5.5" }, "pylint-plugin-utils": { "hashes": [ @@ -966,19 +975,19 @@ }, "rich": { "hashes": [ - "sha256:2b38e2fe9ca72c9a00170a1a2d20c63c790d0e10ef1fe35eba76e1e7b1d7d245", - "sha256:5c14d22737e6d5084ef4771b62d5d4363165b403455a30a1c8ca39dc7b644bef" + "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", + "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" ], "markers": "python_full_version >= '3.7.0'", - "version": "==13.6.0" + "version": "==13.7.0" }, "setuptools": { "hashes": [ - "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87", - "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a" + "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05", + "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78" ], "markers": "python_version >= '3.8'", - "version": "==68.2.2" + "version": "==69.0.3" }, "six": { "hashes": [ @@ -1014,108 +1023,27 @@ }, "tomlkit": { "hashes": [ - "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86", - "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899" + "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4", + "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba" ], "markers": "python_version >= '3.7'", - "version": "==0.12.1" + "version": "==0.12.3" }, "typing-extensions": { "hashes": [ - "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", - "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" ], "markers": "python_version < '3.11'", - "version": "==4.8.0" + "version": "==4.9.0" }, "virtualenv": { "hashes": [ - "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b", - "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752" + "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3", + "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b" ], "markers": "python_version >= '3.7'", - "version": "==20.24.5" - }, - "wrapt": { - "hashes": [ - "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0", - "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420", - "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a", - "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c", - "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079", - "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", - "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f", - "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", - "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8", - "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86", - "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", - "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364", - "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e", - "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", - "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", - "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c", - "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", - "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff", - "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e", - "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29", - "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", - "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", - "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475", - "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a", - "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317", - "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2", - "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd", - "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", - "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", - "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248", - "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", - "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d", - "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", - "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1", - "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e", - "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9", - "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", - "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb", - "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094", - "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46", - "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29", - "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd", - "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", - "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8", - "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", - "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", - "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e", - "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b", - "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418", - "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019", - "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1", - "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba", - "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6", - "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2", - "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", - "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", - "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752", - "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", - "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f", - "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1", - "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc", - "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145", - "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", - "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", - "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7", - "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b", - "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653", - "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0", - "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", - "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29", - "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6", - "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", - "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", - "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", - "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" - ], - "markers": "python_version < '3.11'", - "version": "==1.15.0" + "version": "==20.25.0" } } } From c350fdcb936836e06176a9f53f688ef4604e129e Mon Sep 17 00:00:00 2001 From: tncrdk Date: Tue, 9 Jan 2024 18:54:12 +0100 Subject: [PATCH 13/18] formatting --- nablapps/mailfeed/apps.py | 2 +- nablapps/mailfeed/migrations/0001_initial.py | 50 ++++++++++++++----- .../migrations/0002_auto_20240109_1653.py | 15 +++--- .../migrations/0003_alter_mailfeed_options.py | 7 ++- nablapps/mailfeed/urls.py | 4 +- 5 files changed, 50 insertions(+), 28 deletions(-) diff --git a/nablapps/mailfeed/apps.py b/nablapps/mailfeed/apps.py index 3187e2d8..1ce783da 100644 --- a/nablapps/mailfeed/apps.py +++ b/nablapps/mailfeed/apps.py @@ -2,4 +2,4 @@ class MailfeedConfig(AppConfig): - name = 'nablapps.mailfeed' + name = "nablapps.mailfeed" diff --git a/nablapps/mailfeed/migrations/0001_initial.py b/nablapps/mailfeed/migrations/0001_initial.py index 254f533f..544b21a5 100644 --- a/nablapps/mailfeed/migrations/0001_initial.py +++ b/nablapps/mailfeed/migrations/0001_initial.py @@ -5,28 +5,54 @@ class Migration(migrations.Migration): - initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='MailFeed', + name="MailFeed", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', models.DateTimeField(auto_created=True, verbose_name='Opprettet')), - ('name', models.CharField(max_length=40)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + models.DateTimeField(auto_created=True, verbose_name="Opprettet"), + ), + ("name", models.CharField(max_length=40)), ], ), migrations.CreateModel( - name='Subscription', + name="Subscription", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', models.DateTimeField(auto_created=True, verbose_name='Opprettet')), - ('email', models.EmailField(max_length=254)), - ('mailfeed', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mailfeed.mailfeed')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + models.DateTimeField(auto_created=True, verbose_name="Opprettet"), + ), + ("email", models.EmailField(max_length=254)), + ( + "mailfeed", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="mailfeed.mailfeed", + ), + ), ], ), ] diff --git a/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py b/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py index a7eb8b31..43f46996 100644 --- a/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py +++ b/nablapps/mailfeed/migrations/0002_auto_20240109_1653.py @@ -4,20 +4,19 @@ class Migration(migrations.Migration): - dependencies = [ - ('mailfeed', '0001_initial'), + ("mailfeed", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='mailfeed', - name='created', - field=models.DateTimeField(auto_now=True, verbose_name='Opprettet'), + model_name="mailfeed", + name="created", + field=models.DateTimeField(auto_now=True, verbose_name="Opprettet"), ), migrations.AlterField( - model_name='subscription', - name='created', - field=models.DateTimeField(auto_now=True, verbose_name='Opprettet'), + model_name="subscription", + name="created", + field=models.DateTimeField(auto_now=True, verbose_name="Opprettet"), ), ] diff --git a/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py b/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py index 66006269..bf7da85d 100644 --- a/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py +++ b/nablapps/mailfeed/migrations/0003_alter_mailfeed_options.py @@ -4,14 +4,13 @@ class Migration(migrations.Migration): - dependencies = [ - ('mailfeed', '0002_auto_20240109_1653'), + ("mailfeed", "0002_auto_20240109_1653"), ] operations = [ migrations.AlterModelOptions( - name='mailfeed', - options={'permissions': [('generate_mailfeeds', 'can generate mailfeeds')]}, + name="mailfeed", + options={"permissions": [("generate_mailfeeds", "can generate mailfeeds")]}, ), ] diff --git a/nablapps/mailfeed/urls.py b/nablapps/mailfeed/urls.py index c70d3256..590f8f4a 100644 --- a/nablapps/mailfeed/urls.py +++ b/nablapps/mailfeed/urls.py @@ -14,9 +14,7 @@ MailFeedDetailView.as_view(), name="mailfeed-detail", ), - path( - "create-mailfeed/", CreateMailFeedView.as_view(), name="create-mailfeed" - ), + path("create-mailfeed/", CreateMailFeedView.as_view(), name="create-mailfeed"), path( "subscribe//", SubscribeView.as_view(), From 33095ff70fa1b4779633bbf19649b7565396da92 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Wed, 10 Jan 2024 09:43:00 +0100 Subject: [PATCH 14/18] added type hints --- nablapps/mailfeed/forms.py | 8 ++++---- nablapps/mailfeed/models.py | 2 +- nablapps/mailfeed/views.py | 11 +++++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/nablapps/mailfeed/forms.py b/nablapps/mailfeed/forms.py index 7339e3ef..0b0ea604 100644 --- a/nablapps/mailfeed/forms.py +++ b/nablapps/mailfeed/forms.py @@ -4,7 +4,7 @@ class MailFeedForm(forms.Form): name_field = forms.CharField(required=True) - def get_name(self): + def get_name(self) -> str: cd = self.cleaned_data name = cd["name_field"] return name @@ -13,7 +13,7 @@ def get_name(self): class SubscribeForm(forms.Form): email_field = forms.EmailField(widget=forms.EmailInput) - def get_email(self): + def get_email(self) -> str: cd = self.cleaned_data email = cd["email_field"] return email @@ -23,12 +23,12 @@ class EmailForm(forms.Form): subject_field = forms.CharField(max_length=80) content_field = forms.CharField(required=True, widget=forms.Textarea) - def get_subject(self): + def get_subject(self) -> str: cd = self.cleaned_data subject = cd["subject_field"] return subject - def get_content(self): + def get_content(self) -> str: cd = self.cleaned_data content = cd["content_field"] return content diff --git a/nablapps/mailfeed/models.py b/nablapps/mailfeed/models.py index feeccda9..e6063630 100644 --- a/nablapps/mailfeed/models.py +++ b/nablapps/mailfeed/models.py @@ -5,7 +5,7 @@ class Mailfeed(models.Model): name = models.CharField(max_length=40, blank=False, null=False) created = models.DateTimeField(auto_now=True, verbose_name="Opprettet") - def get_email_list(self): + def get_email_list(self) -> list[str]: subscription_list = Subscription.objects.filter(mailfeed=self) email_list = [sub.email for sub in subscription_list] return email_list diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py index cd10d731..b36491f5 100644 --- a/nablapps/mailfeed/views.py +++ b/nablapps/mailfeed/views.py @@ -42,14 +42,14 @@ def post(self, request): class SubscribeView(View): - def get(self, request, mailfeed_id): + def get(self, request, mailfeed_id: int): subscribe_form = SubscribeForm() context = {"subscribe_form": subscribe_form} mailfeed = Mailfeed.objects.get(pk=mailfeed_id) context["mailfeed"] = mailfeed return render(request, "mailfeed/subscribe_mailfeed.html", context) - def post(self, request, mailfeed_id): + def post(self, request, mailfeed_id: int): mailfeed = Mailfeed.objects.get(pk=mailfeed_id) subscribe_form = SubscribeForm(request.POST) if subscribe_form.is_valid(): @@ -71,10 +71,13 @@ def post(self, request, mailfeed_id): return render(request, "mailfeed/invalid_email.html", {"mailfeed": mailfeed}) +# TODO: Lag unsubscribe view som som kan legges ved som lenke i mailen. + + class MailFeedDetailView(PermissionRequiredMixin, DetailView): permission_required = "Mailfeed.generate_mailfeeds" - def get(self, request, mailfeed_id): + def get(self, request, mailfeed_id: int): email_form = EmailForm() context = {"email_form": email_form} mailfeed = Mailfeed.objects.get(pk=mailfeed_id) @@ -83,7 +86,7 @@ def get(self, request, mailfeed_id): context["email_list"] = email_list return render(request, "mailfeed/mailfeed_detail.html", context) - def post(self, request, mailfeed_id): + def post(self, request, mailfeed_id: int): email_form = EmailForm(request.POST) mailfeed = Mailfeed.objects.get(pk=mailfeed_id) email_list = mailfeed.get_email_list() From 3aabe8df128759d42a889f838f50cfaa9ba6f848 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Wed, 10 Jan 2024 19:02:40 +0100 Subject: [PATCH 15/18] add: unsubscribe-site for unsubscribing from a mailfeed --- nablapps/mailfeed/forms.py | 9 +++ .../0004_subscription_email_hash.py | 19 ++++++ .../migrations/0005_auto_20240110_1725.py | 23 +++++++ nablapps/mailfeed/models.py | 9 +++ .../mailfeed/unsubscribe_mailfeed.html | 15 +++++ nablapps/mailfeed/urls.py | 6 ++ nablapps/mailfeed/views.py | 66 +++++++++++++++++-- 7 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 nablapps/mailfeed/migrations/0004_subscription_email_hash.py create mode 100644 nablapps/mailfeed/migrations/0005_auto_20240110_1725.py create mode 100644 nablapps/mailfeed/templates/mailfeed/unsubscribe_mailfeed.html diff --git a/nablapps/mailfeed/forms.py b/nablapps/mailfeed/forms.py index 0b0ea604..cec2050c 100644 --- a/nablapps/mailfeed/forms.py +++ b/nablapps/mailfeed/forms.py @@ -19,6 +19,15 @@ def get_email(self) -> str: return email +class UnsubscribeForm(forms.Form): + checkbox_field = forms.BooleanField() + + def get_result(self) -> bool: + cd = self.cleaned_data + result = cd["checkbox_field"] + return result + + class EmailForm(forms.Form): subject_field = forms.CharField(max_length=80) content_field = forms.CharField(required=True, widget=forms.Textarea) diff --git a/nablapps/mailfeed/migrations/0004_subscription_email_hash.py b/nablapps/mailfeed/migrations/0004_subscription_email_hash.py new file mode 100644 index 00000000..c90e2cf8 --- /dev/null +++ b/nablapps/mailfeed/migrations/0004_subscription_email_hash.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.23 on 2024-01-10 16:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailfeed', '0003_alter_mailfeed_options'), + ] + + operations = [ + migrations.AddField( + model_name='subscription', + name='email_hash', + field=models.CharField(default='asdf', max_length=100), + preserve_default=False, + ), + ] diff --git a/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py b/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py new file mode 100644 index 00000000..ed9917e7 --- /dev/null +++ b/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.23 on 2024-01-10 17:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailfeed', '0004_subscription_email_hash'), + ] + + operations = [ + migrations.RemoveField( + model_name='subscription', + name='email_hash', + ), + migrations.AddField( + model_name='subscription', + name='uuid', + field=models.CharField(default=23, max_length=150), + preserve_default=False, + ), + ] diff --git a/nablapps/mailfeed/models.py b/nablapps/mailfeed/models.py index e6063630..1d770116 100644 --- a/nablapps/mailfeed/models.py +++ b/nablapps/mailfeed/models.py @@ -1,4 +1,5 @@ from django.db import models +from uuid import uuid4 class Mailfeed(models.Model): @@ -15,8 +16,16 @@ class Meta: ("generate_mailfeeds", "can generate mailfeeds"), ] + def __str__(self) -> str: + return self.name + class Subscription(models.Model): mailfeed = models.ForeignKey(Mailfeed, on_delete=models.CASCADE) email = models.EmailField(blank=False, null=False) + uuid = models.CharField(max_length=150) created = models.DateTimeField(auto_now=True, verbose_name="Opprettet") + + def save(self, *args, **kwargs): + self.uuid = uuid4() + super(Subscription, self).save(*args, **kwargs) diff --git a/nablapps/mailfeed/templates/mailfeed/unsubscribe_mailfeed.html b/nablapps/mailfeed/templates/mailfeed/unsubscribe_mailfeed.html new file mode 100644 index 00000000..2d63fd18 --- /dev/null +++ b/nablapps/mailfeed/templates/mailfeed/unsubscribe_mailfeed.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block content %} +

Slutt å abonner på {{ mailfeed.name }}

+ + + + {% csrf_token %} + {{ unsubscribe_form.checkbox_field }} +
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/nablapps/mailfeed/urls.py b/nablapps/mailfeed/urls.py index 590f8f4a..139225b3 100644 --- a/nablapps/mailfeed/urls.py +++ b/nablapps/mailfeed/urls.py @@ -5,6 +5,7 @@ MailFeedDetailView, MailFeedListView, SubscribeView, + UnsubscribeView, ) urlpatterns = [ @@ -20,4 +21,9 @@ SubscribeView.as_view(), name="subscribe-mailfeed", ), + path( + "unsubscribe//", + UnsubscribeView.as_view(), + name="unsubscribe-mailfeed", + ), ] diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py index b36491f5..3dfdebb7 100644 --- a/nablapps/mailfeed/views.py +++ b/nablapps/mailfeed/views.py @@ -3,13 +3,13 @@ from django.core.mail import BadHeaderError, send_mail from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.mail import BadHeaderError, send_mail -from django.http import HttpResponse +from django.http import HttpResponse, HttpRequest from django.shortcuts import redirect, render from django.urls import reverse from django.views import View from django.views.generic import DetailView, ListView -from .forms import SubscribeForm, MailFeedForm, EmailForm +from .forms import SubscribeForm, MailFeedForm, EmailForm, UnsubscribeForm class MailFeedListView(PermissionRequiredMixin, ListView): @@ -71,7 +71,49 @@ def post(self, request, mailfeed_id: int): return render(request, "mailfeed/invalid_email.html", {"mailfeed": mailfeed}) -# TODO: Lag unsubscribe view som som kan legges ved som lenke i mailen. +class UnsubscribeView(View): + def get(self, request, mailfeed_id: int, uuid: str): + unsubscribe_form = UnsubscribeForm() + context = {"unsubscribe_form": unsubscribe_form} + mailfeed = Mailfeed.objects.get(pk=mailfeed_id) + subscription = Subscription.objects.filter(mailfeed=mailfeed, uuid=uuid).first() + if subscription is None: + return render(request, "404.html") + context["mailfeed"] = mailfeed + return render(request, "mailfeed/unsubscribe_mailfeed.html", context) + + def post(self, request, mailfeed_id: int, uuid: str): + mailfeed = Mailfeed.objects.get(pk=mailfeed_id) + subscription = Subscription.objects.filter(mailfeed=mailfeed, uuid=uuid).first() + print(subscription) + + if subscription == None: + return render( + request, + "mailfeed/msg.html", + {"msg": f"Denne mailadressen abonnerer ikke på {mailfeed.name}"}, + ) + + unsubscribe_form = UnsubscribeForm(request.POST) + if unsubscribe_form.is_valid(): + result = unsubscribe_form.get_result() + if result: + subscription.delete() + return render( + request, + "mailfeed/msg.html", + { + "msg": f"{subscription.email} har sluttet å abonnere på {mailfeed.name}" + }, + ) + else: + redirect( + reverse( + "mailfeed/unsubscribe_mailfeed.html", + kwargs={"mailfeed_id": mailfeed_id, "email_hash": uuid}, + ) + ) + return render(request, "mailfeed/msg.html", {"msg": "Noe gikk galt!"}) class MailFeedDetailView(PermissionRequiredMixin, DetailView): @@ -86,7 +128,7 @@ def get(self, request, mailfeed_id: int): context["email_list"] = email_list return render(request, "mailfeed/mailfeed_detail.html", context) - def post(self, request, mailfeed_id: int): + def post(self, request: HttpRequest, mailfeed_id: int): email_form = EmailForm(request.POST) mailfeed = Mailfeed.objects.get(pk=mailfeed_id) email_list = mailfeed.get_email_list() @@ -94,8 +136,22 @@ def post(self, request, mailfeed_id: int): return HttpResponse("Oops! Noe gikk galt.") subject = email_form.get_subject() - content = email_form.get_content() for email in email_list: + subscription = Subscription.objects.filter( + mailfeed=mailfeed, email=email + ).first() + if subscription is None: + return HttpResponse("Noe gikk galt. Prøv igjen senere.") + content = email_form.get_content() + content += ( + f"\n\nHvis du vil slutte å abonnere på disse mailene trykk her:\n" + ) + print(request.build_absolute_uri("unsubscribe-mailfeed")) + unsubscribe_url = "https://nabla.no" + reverse( + "unsubscribe-mailfeed", + kwargs={"mailfeed_id": mailfeed_id, "uuid": subscription.uuid}, + ) + content += unsubscribe_url try: send_mail( subject, From dc69d74996bd27caa178808c94b6322410af2015 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Wed, 10 Jan 2024 19:03:05 +0100 Subject: [PATCH 16/18] fix: improved admin display of Subscription --- nablapps/mailfeed/admin.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/nablapps/mailfeed/admin.py b/nablapps/mailfeed/admin.py index 3b556bf9..8cf9609b 100644 --- a/nablapps/mailfeed/admin.py +++ b/nablapps/mailfeed/admin.py @@ -3,5 +3,25 @@ # Register your models here. from .models import Subscription, Mailfeed -admin.site.register(Subscription) + +class SubscriptionAdmin(admin.ModelAdmin): + class Meta: + verbose_name = "Subscription" + verbose_name_plural = "Subscriptions" + + def short_description(self, com): + return (com.story[:23] + "...") if len(com.story) > 25 else com.story + + def full_user_name(self, com): + return com.user.get_full_name() + + list_display = ("mailfeed", "email", "uuid", "created") + list_select_related = [ + "mailfeed", + ] + ordering = ["-mailfeed"] + list_filter = ["mailfeed", "email"] + + +admin.site.register(Subscription, SubscriptionAdmin) admin.site.register(Mailfeed) From 5a4c4f5e0beed9c978c0d9be18e61483fdce480e Mon Sep 17 00:00:00 2001 From: tncrdk Date: Fri, 12 Jan 2024 15:24:06 +0100 Subject: [PATCH 17/18] fixed wrong url in the unsubscribe_view --- nablapps/mailfeed/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py index 3dfdebb7..8e466738 100644 --- a/nablapps/mailfeed/views.py +++ b/nablapps/mailfeed/views.py @@ -109,8 +109,8 @@ def post(self, request, mailfeed_id: int, uuid: str): else: redirect( reverse( - "mailfeed/unsubscribe_mailfeed.html", - kwargs={"mailfeed_id": mailfeed_id, "email_hash": uuid}, + "unsubscribe-mailfeed", + kwargs={"mailfeed_id": mailfeed_id, "uuid": uuid}, ) ) return render(request, "mailfeed/msg.html", {"msg": "Noe gikk galt!"}) From d41df0e9ca0a948e0128bb63ef4d1ba9fb378331 Mon Sep 17 00:00:00 2001 From: tncrdk Date: Fri, 12 Jan 2024 15:31:42 +0100 Subject: [PATCH 18/18] formatted the code with fixme --- nablapps/mailfeed/admin.py | 2 +- nablapps/mailfeed/migrations/0001_initial.py | 2 +- .../migrations/0004_subscription_email_hash.py | 9 ++++----- .../mailfeed/migrations/0005_auto_20240110_1725.py | 11 +++++------ nablapps/mailfeed/models.py | 3 ++- nablapps/mailfeed/views.py | 8 +++----- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/nablapps/mailfeed/admin.py b/nablapps/mailfeed/admin.py index 8cf9609b..9955b3a7 100644 --- a/nablapps/mailfeed/admin.py +++ b/nablapps/mailfeed/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin # Register your models here. -from .models import Subscription, Mailfeed +from .models import Mailfeed, Subscription class SubscriptionAdmin(admin.ModelAdmin): diff --git a/nablapps/mailfeed/migrations/0001_initial.py b/nablapps/mailfeed/migrations/0001_initial.py index 544b21a5..a9395182 100644 --- a/nablapps/mailfeed/migrations/0001_initial.py +++ b/nablapps/mailfeed/migrations/0001_initial.py @@ -1,7 +1,7 @@ # Generated by Django 3.2.22 on 2024-01-08 23:34 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/nablapps/mailfeed/migrations/0004_subscription_email_hash.py b/nablapps/mailfeed/migrations/0004_subscription_email_hash.py index c90e2cf8..03d35ddb 100644 --- a/nablapps/mailfeed/migrations/0004_subscription_email_hash.py +++ b/nablapps/mailfeed/migrations/0004_subscription_email_hash.py @@ -4,16 +4,15 @@ class Migration(migrations.Migration): - dependencies = [ - ('mailfeed', '0003_alter_mailfeed_options'), + ("mailfeed", "0003_alter_mailfeed_options"), ] operations = [ migrations.AddField( - model_name='subscription', - name='email_hash', - field=models.CharField(default='asdf', max_length=100), + model_name="subscription", + name="email_hash", + field=models.CharField(default="asdf", max_length=100), preserve_default=False, ), ] diff --git a/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py b/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py index ed9917e7..d9fffd0b 100644 --- a/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py +++ b/nablapps/mailfeed/migrations/0005_auto_20240110_1725.py @@ -4,19 +4,18 @@ class Migration(migrations.Migration): - dependencies = [ - ('mailfeed', '0004_subscription_email_hash'), + ("mailfeed", "0004_subscription_email_hash"), ] operations = [ migrations.RemoveField( - model_name='subscription', - name='email_hash', + model_name="subscription", + name="email_hash", ), migrations.AddField( - model_name='subscription', - name='uuid', + model_name="subscription", + name="uuid", field=models.CharField(default=23, max_length=150), preserve_default=False, ), diff --git a/nablapps/mailfeed/models.py b/nablapps/mailfeed/models.py index 1d770116..482cdf2f 100644 --- a/nablapps/mailfeed/models.py +++ b/nablapps/mailfeed/models.py @@ -1,6 +1,7 @@ -from django.db import models from uuid import uuid4 +from django.db import models + class Mailfeed(models.Model): name = models.CharField(max_length=40, blank=False, null=False) diff --git a/nablapps/mailfeed/views.py b/nablapps/mailfeed/views.py index 8e466738..7ec1f165 100644 --- a/nablapps/mailfeed/views.py +++ b/nablapps/mailfeed/views.py @@ -1,15 +1,13 @@ -from .models import Mailfeed, Subscription - -from django.core.mail import BadHeaderError, send_mail from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.mail import BadHeaderError, send_mail -from django.http import HttpResponse, HttpRequest +from django.http import HttpRequest, HttpResponse from django.shortcuts import redirect, render from django.urls import reverse from django.views import View from django.views.generic import DetailView, ListView -from .forms import SubscribeForm, MailFeedForm, EmailForm, UnsubscribeForm +from .forms import EmailForm, MailFeedForm, SubscribeForm, UnsubscribeForm +from .models import Mailfeed, Subscription class MailFeedListView(PermissionRequiredMixin, ListView):