codeforlife-portal 6.41.5__py2.py3-none-any.whl → 6.41.6__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codeforlife-portal might be problematic. Click here for more details.

Files changed (49) hide show
  1. cfl_common/common/app_settings.py +3 -0
  2. cfl_common/common/email_messages.py +0 -58
  3. cfl_common/common/helpers/data_migration_loader.py +3 -4
  4. cfl_common/common/helpers/emails.py +27 -45
  5. cfl_common/common/helpers/generators.py +1 -1
  6. cfl_common/common/mail.py +116 -0
  7. cfl_common/common/migrations/0002_emailverification.py +1 -3
  8. cfl_common/common/migrations/0005_add_worksheets.py +1 -5
  9. cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py +1 -5
  10. cfl_common/common/migrations/0008_unlock_worksheet_3.py +1 -5
  11. cfl_common/common/migrations/0017_copy_email_to_username.py +2 -8
  12. cfl_common/common/migrations/0021_school_is_active.py +7 -7
  13. cfl_common/common/migrations/0022_school_cleanup.py +9 -9
  14. cfl_common/common/migrations/0023_userprofile_aimmo_badges.py +4 -4
  15. cfl_common/common/migrations/0025_schoolteacherinvitation.py +29 -13
  16. cfl_common/common/migrations/0026_teacher_remove_join_request.py +5 -5
  17. cfl_common/common/migrations/0027_class_created_by.py +10 -4
  18. cfl_common/common/migrations/0028_coding_club_downloads.py +5 -5
  19. cfl_common/common/migrations/0029_dynamicelement.py +6 -6
  20. cfl_common/common/migrations/0030_add_maintenance_banner.py +1 -3
  21. cfl_common/common/migrations/0031_improve_admin_panel.py +32 -14
  22. cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py +3 -3
  23. cfl_common/common/migrations/0033_password_reset_tracking_fields.py +5 -5
  24. cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py +3 -3
  25. cfl_common/common/migrations/0035_rename_lockout_fields.py +10 -10
  26. cfl_common/common/migrations/0037_migrate_email_verification.py +2 -2
  27. cfl_common/common/migrations/0038_delete_emailverification.py +2 -2
  28. cfl_common/common/migrations/0039_copy_email_to_username.py +1 -6
  29. cfl_common/common/migrations/0040_school_county.py +3 -3
  30. cfl_common/common/migrations/0042_totalactivity.py +7 -7
  31. cfl_common/common/migrations/0044_update_activity_models.py +9 -9
  32. cfl_common/common/migrations/0045_otp.py +5 -5
  33. cfl_common/common/migrations/0046_alter_school_country.py +3 -3
  34. cfl_common/common/tests/utils/email.py +14 -34
  35. cfl_common/common/tests/utils/student.py +8 -8
  36. cfl_common/common/tests/utils/teacher.py +8 -8
  37. {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/METADATA +2 -2
  38. {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/RECORD +49 -48
  39. example_project/portal_test_settings.py +5 -1
  40. portal/__init__.py +1 -1
  41. portal/tests/test_independent_student.py +30 -17
  42. portal/tests/test_ratelimit.py +15 -12
  43. portal/tests/test_teacher.py +35 -21
  44. portal/tests/test_teacher_student.py +13 -3
  45. portal/tests/test_views.py +55 -194
  46. portal/views/cron/user.py +12 -49
  47. {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/LICENSE.md +0 -0
  48. {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/WHEEL +0 -0
  49. {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,6 @@ from unittest.mock import ANY, Mock, patch
7
7
  import PyPDF2
8
8
  import pytest
9
9
  from aimmo.models import Game
10
- from common.helpers.emails import NOTIFICATION_EMAIL
11
10
  from common.models import (
12
11
  Class,
13
12
  DailyActivity,
@@ -55,9 +54,7 @@ class TestTeacherViews(TestCase):
55
54
  def setUpTestData(cls):
56
55
  cls.email, cls.password = signup_teacher_directly()
57
56
  _, _, cls.class_access_code = create_class_directly(cls.email)
58
- _, _, cls.student = create_school_student_directly(
59
- cls.class_access_code
60
- )
57
+ _, _, cls.student = create_school_student_directly(cls.class_access_code)
61
58
 
62
59
  def login(self):
63
60
  c = Client()
@@ -66,9 +63,7 @@ class TestTeacherViews(TestCase):
66
63
 
67
64
  def test_reminder_cards(self):
68
65
  c = self.login()
69
- url = reverse(
70
- "teacher_print_reminder_cards", args=[self.class_access_code]
71
- )
66
+ url = reverse("teacher_print_reminder_cards", args=[self.class_access_code])
72
67
 
73
68
  # First test with 2 dummy students
74
69
  NAME1 = "Test name"
@@ -102,9 +97,7 @@ class TestTeacherViews(TestCase):
102
97
  # page number
103
98
  students_per_page = REMINDER_CARDS_PDF_ROWS * REMINDER_CARDS_PDF_COLUMNS
104
99
  for _ in range(len(studentlist), students_per_page + 1):
105
- studentlist.append(
106
- {"name": NAME1, "password": PASSWORD1, "login_url": URL}
107
- )
100
+ studentlist.append({"name": NAME1, "password": PASSWORD1, "login_url": URL})
108
101
 
109
102
  assert len(studentlist) == students_per_page + 1
110
103
 
@@ -143,9 +136,7 @@ class TestTeacherViews(TestCase):
143
136
  reader = csv.reader(io.StringIO(content))
144
137
 
145
138
  access_code = self.class_access_code
146
- class_url = reverse(
147
- "student_login", kwargs={"access_code": access_code}
148
- )
139
+ class_url = reverse("student_login", kwargs={"access_code": access_code})
149
140
  row0 = next(reader)
150
141
  assert row0[0].strip() == access_code
151
142
  assert class_url in row0[1].strip()
@@ -184,9 +175,7 @@ class TestTeacherViews(TestCase):
184
175
 
185
176
  def test_daily_activity_student_details(self):
186
177
  c = self.login()
187
- url = reverse(
188
- "teacher_print_reminder_cards", args=[self.class_access_code]
189
- )
178
+ url = reverse("teacher_print_reminder_cards", args=[self.class_access_code])
190
179
 
191
180
  data = {
192
181
  "data": json.dumps(
@@ -249,9 +238,7 @@ class TestLoginViews(TestCase):
249
238
  teacher_email, teacher_password = signup_teacher_directly()
250
239
  create_organisation_directly(teacher_email)
251
240
  _, _, class_access_code = create_class_directly(teacher_email)
252
- student_name, student_password, _ = create_school_student_directly(
253
- class_access_code
254
- )
241
+ student_name, student_password, _ = create_school_student_directly(class_access_code)
255
242
 
256
243
  return (
257
244
  teacher_email,
@@ -284,16 +271,9 @@ class TestLoginViews(TestCase):
284
271
  _, _, name, password, class_access_code = self._set_up_test_data()
285
272
 
286
273
  if next_url:
287
- url = (
288
- reverse(
289
- "student_login", kwargs={"access_code": class_access_code}
290
- )
291
- + "?next=/"
292
- )
274
+ url = reverse("student_login", kwargs={"access_code": class_access_code}) + "?next=/"
293
275
  else:
294
- url = reverse(
295
- "student_login", kwargs={"access_code": class_access_code}
296
- )
276
+ url = reverse("student_login", kwargs={"access_code": class_access_code})
297
277
 
298
278
  c = Client()
299
279
  response = c.post(url, {"username": name, "password": password})
@@ -332,9 +312,7 @@ class TestLoginViews(TestCase):
332
312
 
333
313
  def _get_user_class(self, name, class_access_code):
334
314
  klass = Class.objects.get(access_code=class_access_code)
335
- students = Student.objects.filter(
336
- new_user__first_name__iexact=name, class_field=klass
337
- )
315
+ students = Student.objects.filter(new_user__first_name__iexact=name, class_field=klass)
338
316
  assert len(students) == 1
339
317
  user = students[0].new_user
340
318
  return user, klass
@@ -376,9 +354,7 @@ class TestLoginViews(TestCase):
376
354
  _, _, name, password, class_access_code = self._set_up_test_data()
377
355
 
378
356
  c = Client()
379
- url = reverse(
380
- "student_login", kwargs={"access_code": class_access_code}
381
- )
357
+ url = reverse("student_login", kwargs={"access_code": class_access_code})
382
358
  c.post(url, {"username": name, "password": password})
383
359
 
384
360
  # check if there's a UserSession data within the last 10 secs
@@ -399,9 +375,7 @@ class TestLoginViews(TestCase):
399
375
  randomname = "randomname"
400
376
 
401
377
  c = Client()
402
- url = reverse(
403
- "student_login", kwargs={"access_code": class_access_code}
404
- )
378
+ url = reverse("student_login", kwargs={"access_code": class_access_code})
405
379
  c.post(url, {"username": randomname, "password": "xx"})
406
380
 
407
381
  # check if there's a UserSession data within the last 10 secs
@@ -427,9 +401,7 @@ class TestLoginViews(TestCase):
427
401
 
428
402
  def test_student_direct_login(self):
429
403
  _, _, _, _, class_access_code = self._set_up_test_data()
430
- student, login_id, _, _ = create_student_with_direct_login(
431
- class_access_code
432
- )
404
+ student, login_id, _, _ = create_student_with_direct_login(class_access_code)
433
405
 
434
406
  c = Client()
435
407
  assert c.login(user_id=student.new_user.id, login_id=login_id) == True
@@ -551,9 +523,7 @@ class TestViews(TestCase):
551
523
  c = Client()
552
524
 
553
525
  # Login and check initial data
554
- url = reverse(
555
- "student_login", kwargs={"access_code": class_access_code}
556
- )
526
+ url = reverse("student_login", kwargs={"access_code": class_access_code})
557
527
  c.post(url, {"username": student_name, "password": student_password})
558
528
 
559
529
  student_dashboard_url = reverse("student_details")
@@ -631,9 +601,7 @@ class TestViews(TestCase):
631
601
 
632
602
  # try again with the correct password
633
603
  url = reverse("delete_account")
634
- response = c.post(
635
- url, {"password": password, "unsubscribe_newsletter": "on"}
636
- )
604
+ response = c.post(url, {"password": password, "unsubscribe_newsletter": "on"})
637
605
 
638
606
  assert response.status_code == 302
639
607
  assert response.url == reverse("home")
@@ -710,9 +678,7 @@ class TestViews(TestCase):
710
678
 
711
679
  school_id = school.id
712
680
  school_name = school.name
713
- teachers = Teacher.objects.filter(school=school).order_by(
714
- "new_user__last_name", "new_user__first_name"
715
- )
681
+ teachers = Teacher.objects.filter(school=school).order_by("new_user__last_name", "new_user__first_name")
716
682
  assert len(teachers) == 3
717
683
 
718
684
  # one of the remaining teachers should be admin (the second in our case, as it's alphabetical)
@@ -742,9 +708,7 @@ class TestViews(TestCase):
742
708
  c.post(url, {"password": password3})
743
709
 
744
710
  # 2 teachers left
745
- teachers = Teacher.objects.filter(school=school).order_by(
746
- "new_user__last_name", "new_user__first_name"
747
- )
711
+ teachers = Teacher.objects.filter(school=school).order_by("new_user__last_name", "new_user__first_name")
748
712
  assert len(teachers) == 2
749
713
 
750
714
  # teacher2 should still be admin, teacher4 is not passed admin role because there is teacher2
@@ -756,9 +720,7 @@ class TestViews(TestCase):
756
720
  # delete teacher4
757
721
  anonymise(user4)
758
722
 
759
- teachers = Teacher.objects.filter(school=school).order_by(
760
- "new_user__last_name", "new_user__first_name"
761
- )
723
+ teachers = Teacher.objects.filter(school=school).order_by("new_user__last_name", "new_user__first_name")
762
724
  assert len(teachers) == 1
763
725
  u = User.objects.get(id=usrid2)
764
726
  assert u.new_teacher.is_admin
@@ -814,15 +776,14 @@ class TestViews(TestCase):
814
776
 
815
777
  c.logout()
816
778
 
817
- def test_registrations_increment_data(self):
779
+ @patch("common.helpers.emails.send_dotdigital_email")
780
+ def test_registrations_increment_data(self, mock_send_dotdigital_email: Mock):
818
781
  c = Client()
819
782
 
820
783
  total_activity = TotalActivity.objects.get(id=1)
821
784
  teacher_registration_count = total_activity.teacher_registrations
822
785
  student_registration_count = total_activity.student_registrations
823
- independent_registration_count = (
824
- total_activity.independent_registrations
825
- )
786
+ independent_registration_count = total_activity.independent_registrations
826
787
 
827
788
  response = c.post(
828
789
  reverse("register"),
@@ -838,13 +799,11 @@ class TestViews(TestCase):
838
799
  )
839
800
 
840
801
  assert response.status_code == 302
802
+ mock_send_dotdigital_email.assert_called_once()
841
803
 
842
804
  total_activity = TotalActivity.objects.get(id=1)
843
805
 
844
- assert (
845
- total_activity.teacher_registrations
846
- == teacher_registration_count + 1
847
- )
806
+ assert total_activity.teacher_registrations == teacher_registration_count + 1
848
807
 
849
808
  response = c.post(
850
809
  reverse("register"),
@@ -862,13 +821,11 @@ class TestViews(TestCase):
862
821
  )
863
822
 
864
823
  assert response.status_code == 302
824
+ mock_send_dotdigital_email.assert_called()
865
825
 
866
826
  total_activity = TotalActivity.objects.get(id=1)
867
827
 
868
- assert (
869
- total_activity.independent_registrations
870
- == independent_registration_count + 1
871
- )
828
+ assert total_activity.independent_registrations == independent_registration_count + 1
872
829
 
873
830
  teacher_email, teacher_password = signup_teacher_directly()
874
831
  create_organisation_directly(teacher_email)
@@ -884,10 +841,7 @@ class TestViews(TestCase):
884
841
 
885
842
  total_activity = TotalActivity.objects.get(id=1)
886
843
 
887
- assert (
888
- total_activity.student_registrations
889
- == student_registration_count + 3
890
- )
844
+ assert total_activity.student_registrations == student_registration_count + 3
891
845
 
892
846
 
893
847
  # CRON view tests
@@ -906,12 +860,8 @@ class CronTestClient(APIClient):
906
860
  secure=False,
907
861
  **extra,
908
862
  ):
909
- wsgi_response = super().generic(
910
- method, path, data, content_type, secure, **extra
911
- )
912
- assert (
913
- 200 <= wsgi_response.status_code < 300
914
- ), f"Response has error status code: {wsgi_response.status_code}"
863
+ wsgi_response = super().generic(method, path, data, content_type, secure, **extra)
864
+ assert 200 <= wsgi_response.status_code < 300, f"Response has error status code: {wsgi_response.status_code}"
915
865
 
916
866
  return wsgi_response
917
867
 
@@ -930,34 +880,27 @@ class TestUser(CronTestCase):
930
880
  indy_email, _, _ = create_independent_student_directly()
931
881
 
932
882
  self.teacher_user = User.objects.get(email=teacher_email)
933
- self.teacher_user_profile = UserProfile.objects.get(
934
- user=self.teacher_user
935
- )
883
+ self.teacher_user_profile = UserProfile.objects.get(user=self.teacher_user)
936
884
 
937
885
  self.indy_user = User.objects.get(email=indy_email)
938
886
  self.indy_user_profile = UserProfile.objects.get(user=self.indy_user)
939
887
 
940
888
  self.student_user: User = student.new_user
941
889
 
890
+ @patch("portal.views.cron.user.send_dotdigital_email")
942
891
  def send_verify_email_reminder(
943
892
  self,
944
893
  days: int,
945
894
  is_verified: bool,
946
895
  view_name: str,
947
- send_email: Mock,
948
896
  assert_called: bool,
897
+ mock_send_dotdigital_email: Mock,
949
898
  ):
950
- self.teacher_user.date_joined = timezone.now() - timedelta(
951
- days=days, hours=12
952
- )
899
+ self.teacher_user.date_joined = timezone.now() - timedelta(days=days, hours=12)
953
900
  self.teacher_user.save()
954
- self.student_user.date_joined = timezone.now() - timedelta(
955
- days=days, hours=12
956
- )
901
+ self.student_user.date_joined = timezone.now() - timedelta(days=days, hours=12)
957
902
  self.student_user.save()
958
- self.indy_user.date_joined = timezone.now() - timedelta(
959
- days=days, hours=12
960
- )
903
+ self.indy_user.date_joined = timezone.now() - timedelta(days=days, hours=12)
961
904
  self.indy_user.save()
962
905
 
963
906
  self.teacher_user_profile.is_verified = is_verified
@@ -968,100 +911,34 @@ class TestUser(CronTestCase):
968
911
  self.client.get(reverse(view_name))
969
912
 
970
913
  if assert_called:
971
- send_email.assert_any_call(
972
- sender=NOTIFICATION_EMAIL,
973
- recipients=[self.teacher_user.email],
974
- subject=ANY,
975
- title=ANY,
976
- text_content=ANY,
977
- replace_url=ANY,
978
- )
914
+ mock_send_dotdigital_email.assert_any_call(ANY, [self.teacher_user.email], personalization_values=ANY)
979
915
 
980
- send_email.assert_any_call(
981
- sender=NOTIFICATION_EMAIL,
982
- recipients=[self.indy_user.email],
983
- subject=ANY,
984
- title=ANY,
985
- text_content=ANY,
986
- replace_url=ANY,
987
- )
916
+ mock_send_dotdigital_email.assert_any_call(ANY, [self.indy_user.email], personalization_values=ANY)
988
917
 
989
918
  # Check only two emails are sent - the student should never be included.
990
- assert send_email.call_count == 2
919
+ assert mock_send_dotdigital_email.call_count == 2
991
920
  else:
992
- send_email.assert_not_called()
921
+ mock_send_dotdigital_email.assert_not_called()
993
922
 
994
- send_email.reset_mock()
923
+ mock_send_dotdigital_email.reset_mock()
995
924
 
996
- @patch("portal.views.cron.user.send_email")
997
- def test_first_verify_email_reminder_view(self, send_email: Mock):
998
- self.send_verify_email_reminder(
999
- days=6,
1000
- is_verified=False,
1001
- view_name="first-verify-email-reminder",
1002
- send_email=send_email,
1003
- assert_called=False,
1004
- )
1005
- self.send_verify_email_reminder(
1006
- days=7,
1007
- is_verified=False,
1008
- view_name="first-verify-email-reminder",
1009
- send_email=send_email,
1010
- assert_called=True,
1011
- )
1012
- self.send_verify_email_reminder(
1013
- days=7,
1014
- is_verified=True,
1015
- view_name="first-verify-email-reminder",
1016
- send_email=send_email,
1017
- assert_called=False,
1018
- )
1019
- self.send_verify_email_reminder(
1020
- days=8,
1021
- is_verified=False,
1022
- view_name="first-verify-email-reminder",
1023
- send_email=send_email,
1024
- assert_called=False,
1025
- )
925
+ def test_first_verify_email_reminder_view(self):
926
+ self.send_verify_email_reminder(6, False, "first-verify-email-reminder", False)
927
+ self.send_verify_email_reminder(7, False, "first-verify-email-reminder", True)
928
+ self.send_verify_email_reminder(7, True, "first-verify-email-reminder", False)
929
+ self.send_verify_email_reminder(8, False, "first-verify-email-reminder", False)
1026
930
 
1027
- @patch("portal.views.cron.user.send_email")
1028
- def test_second_verify_email_reminder_view(self, send_email: Mock):
1029
- self.send_verify_email_reminder(
1030
- days=13,
1031
- is_verified=False,
1032
- view_name="second-verify-email-reminder",
1033
- send_email=send_email,
1034
- assert_called=False,
1035
- )
1036
- self.send_verify_email_reminder(
1037
- days=14,
1038
- is_verified=False,
1039
- view_name="second-verify-email-reminder",
1040
- send_email=send_email,
1041
- assert_called=True,
1042
- )
1043
- self.send_verify_email_reminder(
1044
- days=14,
1045
- is_verified=True,
1046
- view_name="second-verify-email-reminder",
1047
- send_email=send_email,
1048
- assert_called=False,
1049
- )
1050
- self.send_verify_email_reminder(
1051
- days=15,
1052
- is_verified=False,
1053
- view_name="second-verify-email-reminder",
1054
- send_email=send_email,
1055
- assert_called=False,
1056
- )
931
+ def test_second_verify_email_reminder_view(self):
932
+ self.send_verify_email_reminder(13, False, "second-verify-email-reminder", False)
933
+ self.send_verify_email_reminder(14, False, "second-verify-email-reminder", True)
934
+ self.send_verify_email_reminder(14, True, "second-verify-email-reminder", False)
935
+ self.send_verify_email_reminder(15, False, "second-verify-email-reminder", False)
1057
936
 
1058
937
  def test_anonymise_unverified_accounts_view(self):
1059
938
  now = timezone.now()
1060
939
 
1061
940
  for user in [self.teacher_user, self.indy_user, self.student_user]:
1062
- user.date_joined = now - timedelta(
1063
- days=USER_DELETE_UNVERIFIED_ACCOUNT_DAYS + 1
1064
- )
941
+ user.date_joined = now - timedelta(days=USER_DELETE_UNVERIFIED_ACCOUNT_DAYS + 1)
1065
942
  user.save()
1066
943
 
1067
944
  for user_profile in [self.teacher_user_profile, self.indy_user_profile]:
@@ -1126,9 +1003,7 @@ class TestUser(CronTestCase):
1126
1003
  new_user=indy_user,
1127
1004
  )
1128
1005
 
1129
- activity_today = DailyActivity.objects.get_or_create(
1130
- date=datetime.now().date()
1131
- )[0]
1006
+ activity_today = DailyActivity.objects.get_or_create(date=datetime.now().date())[0]
1132
1007
  daily_teacher_count = activity_today.anonymised_unverified_teachers
1133
1008
  daily_indy_count = activity_today.anonymised_unverified_independents
1134
1009
 
@@ -1151,30 +1026,16 @@ class TestUser(CronTestCase):
1151
1026
  assert indy_user_active == assert_active
1152
1027
  assert student_user_active
1153
1028
 
1154
- activity_today = DailyActivity.objects.get_or_create(
1155
- date=datetime.now().date()
1156
- )[0]
1029
+ activity_today = DailyActivity.objects.get_or_create(date=datetime.now().date())[0]
1157
1030
  total_activity = TotalActivity.objects.get(id=1)
1158
1031
 
1159
1032
  if not teacher_user_active:
1160
- assert (
1161
- activity_today.anonymised_unverified_teachers
1162
- == daily_teacher_count + 1
1163
- )
1164
- assert (
1165
- total_activity.anonymised_unverified_teachers
1166
- == total_teacher_count + 1
1167
- )
1033
+ assert activity_today.anonymised_unverified_teachers == daily_teacher_count + 1
1034
+ assert total_activity.anonymised_unverified_teachers == total_teacher_count + 1
1168
1035
 
1169
1036
  if not indy_user_active:
1170
- assert (
1171
- activity_today.anonymised_unverified_independents
1172
- == daily_indy_count + 1
1173
- )
1174
- assert (
1175
- total_activity.anonymised_unverified_independents
1176
- == total_indy_count + 1
1177
- )
1037
+ assert activity_today.anonymised_unverified_independents == daily_indy_count + 1
1038
+ assert total_activity.anonymised_unverified_independents == total_indy_count + 1
1178
1039
 
1179
1040
  teacher_user.delete()
1180
1041
  indy_user.delete()
portal/views/cron/user.py CHANGED
@@ -1,11 +1,8 @@
1
1
  import logging
2
- from datetime import timedelta, datetime
2
+ from datetime import datetime, timedelta
3
3
 
4
- from common.helpers.emails import (
5
- NOTIFICATION_EMAIL,
6
- generate_token_for_email,
7
- send_email,
8
- )
4
+ from common.helpers.emails import generate_token_for_email
5
+ from common.mail import campaign_ids, send_dotdigital_email
9
6
  from common.models import DailyActivity, TotalActivity
10
7
  from django.contrib.auth.models import User
11
8
  from django.db.models import F
@@ -14,29 +11,14 @@ from django.urls import reverse
14
11
  from django.utils import timezone
15
12
  from rest_framework.response import Response
16
13
  from rest_framework.views import APIView
14
+
17
15
  from portal.views.api import anonymise
18
16
 
19
17
  from ...mixins import CronMixin
20
18
 
21
19
  # TODO: move email templates to DotDigital.
22
20
  USER_1ST_VERIFY_EMAIL_REMINDER_DAYS = 7
23
- USER_1ST_VERIFY_EMAIL_REMINDER_TEXT = (
24
- "Please go to the link below to verify your email address:"
25
- "\n{email_verification_url}."
26
- "\nYou will not be able to use your account until it is verified."
27
- "\n\nBy activating the account you confirm that you have read and agreed to"
28
- " our terms ({terms_url}) and our privacy notice ({privacy_notice_url}). If"
29
- " your account is not verified within 12 days we will delete it."
30
- )
31
21
  USER_2ND_VERIFY_EMAIL_REMINDER_DAYS = 14
32
- USER_2ND_VERIFY_EMAIL_REMINDER_TEXT = (
33
- "Please go to the link below to verify your email address:"
34
- "\n{email_verification_url}."
35
- "\nYou will not be able to use your account until it is verified."
36
- "\n\nBy activating the account you confirm that you have read and agreed to"
37
- " our terms ({terms_url}) and our privacy notice ({privacy_notice_url}). If"
38
- " your account is not verified within 5 days we will delete it."
39
- )
40
22
  USER_DELETE_UNVERIFIED_ACCOUNT_DAYS = 19
41
23
 
42
24
 
@@ -87,9 +69,6 @@ class FirstVerifyEmailReminderView(CronMixin, APIView):
87
69
  logging.info(f"{user_count} emails unverified.")
88
70
 
89
71
  if user_count > 0:
90
- terms_url = build_absolute_google_uri(request, reverse("terms"))
91
- privacy_notice_url = build_absolute_google_uri(request, reverse("privacy_notice"))
92
-
93
72
  sent_email_count = 0
94
73
  for email in user_queryset.values_list("email", flat=True).iterator(chunk_size=500):
95
74
  email_verification_url = build_absolute_google_uri(
@@ -101,17 +80,10 @@ class FirstVerifyEmailReminderView(CronMixin, APIView):
101
80
  )
102
81
 
103
82
  try:
104
- send_email(
105
- sender=NOTIFICATION_EMAIL,
106
- recipients=[email],
107
- subject="Awaiting verification",
108
- title="Awaiting verification",
109
- text_content=USER_1ST_VERIFY_EMAIL_REMINDER_TEXT.format(
110
- email_verification_url=email_verification_url,
111
- terms_url=terms_url,
112
- privacy_notice_url=privacy_notice_url,
113
- ),
114
- replace_url={"verify_url": email_verification_url},
83
+ send_dotdigital_email(
84
+ campaign_ids["verify_new_user_first_reminder"],
85
+ [email],
86
+ personalization_values={"VERIFICATION_LINK": email_verification_url},
115
87
  )
116
88
 
117
89
  sent_email_count += 1
@@ -135,8 +107,6 @@ class SecondVerifyEmailReminderView(CronMixin, APIView):
135
107
  logging.info(f"{user_count} emails unverified.")
136
108
 
137
109
  if user_count > 0:
138
- terms_url = build_absolute_google_uri(request, reverse("terms"))
139
- privacy_notice_url = build_absolute_google_uri(request, reverse("privacy_notice"))
140
110
 
141
111
  sent_email_count = 0
142
112
  for email in user_queryset.values_list("email", flat=True).iterator(chunk_size=500):
@@ -149,17 +119,10 @@ class SecondVerifyEmailReminderView(CronMixin, APIView):
149
119
  )
150
120
 
151
121
  try:
152
- send_email(
153
- sender=NOTIFICATION_EMAIL,
154
- recipients=[email],
155
- subject="Your account needs verification",
156
- title="Your account needs verification",
157
- text_content=USER_2ND_VERIFY_EMAIL_REMINDER_TEXT.format(
158
- email_verification_url=email_verification_url,
159
- terms_url=terms_url,
160
- privacy_notice_url=privacy_notice_url,
161
- ),
162
- replace_url={"verify_url": email_verification_url},
122
+ send_dotdigital_email(
123
+ campaign_ids["verify_new_user_second_reminder"],
124
+ [email],
125
+ personalization_values={"VERIFICATION_LINK": email_verification_url},
163
126
  )
164
127
 
165
128
  sent_email_count += 1