Explorar o código

feat(api): add AuthenticatedChangeOutreachPreferenceUserAction and view

Peter Thomassen %!s(int64=3) %!d(string=hai) anos
pai
achega
25737a4c68

+ 25 - 0
api/desecapi/migrations/0024_authenticatedchangeoutreachpreferenceuseraction.py

@@ -0,0 +1,25 @@
+# Generated by Django 4.0.1 on 2022-01-20 11:21
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('desecapi', '0023_authenticatedemailuseraction'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='AuthenticatedChangeOutreachPreferenceUserAction',
+            fields=[
+                ('authenticatedemailuseraction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='desecapi.authenticatedemailuseraction')),
+                ('outreach_preference', models.BooleanField()),
+            ],
+            options={
+                'managed': False,
+            },
+            bases=('desecapi.authenticatedemailuseraction',),
+        ),
+    ]

+ 12 - 0
api/desecapi/models.py

@@ -169,6 +169,7 @@ class User(ExportModelOperationsMixin('User'), AbstractBaseUser):
             'activate-account': slow_lane,
             'change-email': slow_lane,
             'change-email-confirmation-old-email': fast_lane,
+            'change-outreach-preference': slow_lane,
             'confirm-account': slow_lane,
             'password-change-confirmation': fast_lane,
             'reset-password': fast_lane,
@@ -961,6 +962,17 @@ class AuthenticatedEmailUserAction(AuthenticatedBasicUserAction):
         return super()._state_fields + [self.user.email]
 
 
+class AuthenticatedChangeOutreachPreferenceUserAction(AuthenticatedEmailUserAction):
+    outreach_preference = models.BooleanField(default=False)
+
+    class Meta:
+        managed = False
+
+    def _act(self):
+        self.user.outreach_preference = self.outreach_preference
+        self.user.save()
+
+
 class AuthenticatedUserAction(AuthenticatedEmailUserAction):
     """
     Abstract AuthenticatedBasicUserAction, incorporating the user's id, email, password, and is_active flag into the

+ 9 - 0
api/desecapi/serializers.py

@@ -919,6 +919,15 @@ class AuthenticatedBasicUserActionListSerializer(AuthenticatedBasicUserActionMix
         return user
 
 
+class AuthenticatedChangeOutreachPreferenceUserActionSerializer(AuthenticatedBasicUserActionSerializer):
+    reason = 'change-outreach-preference'
+    validity_period = None
+
+    class Meta:
+        model = models.AuthenticatedChangeOutreachPreferenceUserAction
+        fields = AuthenticatedBasicUserActionSerializer.Meta.fields + ('outreach_preference',)
+
+
 class AuthenticatedActivateUserActionSerializer(AuthenticatedBasicUserActionSerializer):
     captcha = CaptchaSolutionSerializer(required=False)
 

+ 5 - 0
api/desecapi/templates/emails/change-outreach-preference/content.txt

@@ -0,0 +1,5 @@
+{% extends "emails/content.txt" %}
+{% block trailer %}
+Unsubscribe:
+{% load action_extras %}{% action_link action_serializer %}
+{% endblock %}

+ 1 - 0
api/desecapi/urls/version_1.py

@@ -55,6 +55,7 @@ api_urls = [
     # Authenticated Actions
     path('v/activate-account/<code>/', views.AuthenticatedActivateUserActionView.as_view(), name='confirm-activate-account'),
     path('v/change-email/<code>/', views.AuthenticatedChangeEmailUserActionView.as_view(), name='confirm-change-email'),
+    path('v/change-outreach-preference/<code>/', views.AuthenticatedChangeOutreachPreferenceUserActionView.as_view(), name='confirm-change-outreach-preference'),
     path('v/confirm-account/<code>/', views.AuthenticatedConfirmAccountUserAction.as_view(), name='confirm-confirm-account'),
     path('v/reset-password/<code>/', views.AuthenticatedResetPasswordUserActionView.as_view(), name='confirm-reset-password'),
     path('v/delete-account/<code>/', views.AuthenticatedDeleteUserActionView.as_view(), name='confirm-delete-account'),

+ 9 - 0
api/desecapi/views.py

@@ -682,6 +682,15 @@ class AuthenticatedActionView(generics.GenericAPIView):
         return Response(status=status.HTTP_202_ACCEPTED)
 
 
+class AuthenticatedChangeOutreachPreferenceUserActionView(AuthenticatedActionView):
+    html_url = '/confirm/change-outreach-preference/{code}/'
+    serializer_class = serializers.AuthenticatedChangeOutreachPreferenceUserActionSerializer
+
+    def post(self, request, *args, **kwargs):
+        super().post(request, *args, **kwargs)
+        return Response({'detail': 'Thank you! We have recorded that you would not like to receive outreach messages.'})
+
+
 class AuthenticatedActivateUserActionView(AuthenticatedActionView):
     html_url = '/confirm/activate-account/{code}/'
     permission_classes = ()  # don't require that user is activated already