cfl-common 5.3.0__py3-none-any.whl → 8.9.15__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.
Files changed (92) hide show
  1. cfl_common-8.9.15.dist-info/METADATA +47 -0
  2. cfl_common-8.9.15.dist-info/RECORD +99 -0
  3. {cfl_common-5.3.0.dist-info → cfl_common-8.9.15.dist-info}/WHEEL +1 -1
  4. common/app_settings.py +35 -5
  5. common/csp_config.py +85 -0
  6. common/fixtures/aimmo_characters.json +30 -30
  7. common/fixtures/aimmo_characters2.json +1 -1
  8. common/fixtures/aimmo_characters3.json +35 -0
  9. common/helpers/data_migration_loader.py +3 -4
  10. common/helpers/emails.py +228 -108
  11. common/helpers/generators.py +1 -1
  12. common/helpers/organisation.py +10 -0
  13. common/mail.py +201 -0
  14. common/migrations/0002_emailverification.py +1 -3
  15. common/migrations/0005_add_worksheets.py +2 -13
  16. common/migrations/0007_add_pdf_names_to_first_two_worksheets.py +2 -14
  17. common/migrations/0008_unlock_worksheet_3.py +1 -6
  18. common/migrations/0011_student_login_id.py +3 -3
  19. common/migrations/0012_usersession.py +39 -0
  20. common/migrations/0013_class_school.py +42 -0
  21. common/migrations/0014_login_type.py +29 -0
  22. common/migrations/0015_dailyactivity.py +31 -0
  23. common/migrations/0016_joinreleasestudent.py +42 -0
  24. common/migrations/0017_copy_email_to_username.py +18 -0
  25. common/migrations/0018_update_aimmo_character_image_path.py +15 -0
  26. common/migrations/0019_aimmocharacter_alt.py +16 -0
  27. common/migrations/0020_class_is_active_and_null_access_code.py +23 -0
  28. common/migrations/0021_school_is_active.py +28 -0
  29. common/migrations/0022_school_cleanup.py +29 -0
  30. common/migrations/0023_userprofile_aimmo_badges.py +22 -0
  31. common/migrations/0024_teacher_invited_by.py +25 -0
  32. common/migrations/0025_schoolteacherinvitation.py +47 -0
  33. common/migrations/0026_teacher_remove_join_request.py +22 -0
  34. common/migrations/0027_class_created_by.py +25 -0
  35. common/migrations/0028_coding_club_downloads.py +23 -0
  36. common/migrations/0029_dynamicelement.py +22 -0
  37. common/migrations/0030_add_maintenance_banner.py +25 -0
  38. common/migrations/0031_improve_admin_panel.py +56 -0
  39. common/migrations/0032_dailyactivity_level_control_submits.py +18 -0
  40. common/migrations/0033_password_reset_tracking_fields.py +23 -0
  41. common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py +18 -0
  42. common/migrations/0035_rename_lockout_fields.py +27 -0
  43. common/migrations/0036_rename_awaiting_email_verification_userprofile_is_verified.py +17 -0
  44. common/migrations/0037_migrate_email_verification.py +21 -0
  45. common/migrations/0038_delete_emailverification.py +16 -0
  46. common/migrations/0039_copy_email_to_username.py +18 -0
  47. common/migrations/0040_school_county.py +18 -0
  48. common/migrations/0041_populate_gb_counties.py +27 -0
  49. common/migrations/0042_totalactivity.py +25 -0
  50. common/migrations/0043_add_total_activity.py +30 -0
  51. common/migrations/0044_update_activity_models.py +33 -0
  52. common/migrations/0045_otp.py +23 -0
  53. common/migrations/0046_alter_school_country.py +19 -0
  54. common/migrations/0047_delete_school_postcode.py +16 -0
  55. common/migrations/0048_unique_school_names.py +42 -0
  56. common/migrations/0049_anonymise_orphan_users.py +29 -0
  57. common/migrations/0050_anonymise_orphan_schools.py +30 -0
  58. common/migrations/0051_verify_returning_users.py +26 -0
  59. common/migrations/0052_add_cse_fields.py +68 -0
  60. common/migrations/0053_clean_class_data.py +24 -0
  61. common/migrations/0054_delete_aimmo_models.py +20 -0
  62. common/migrations/0055_alter_schoolteacherinvitation_token.py +18 -0
  63. common/migrations/0056_set_non_school_teachers_as_non_admins.py +25 -0
  64. common/migrations/0057_teacher_teacher__is_admin.py +19 -0
  65. common/migrations/0058_userprofile_google_refresh_token_and_more.py +24 -0
  66. common/models.py +347 -63
  67. common/permissions.py +20 -8
  68. common/static/common/img/RR_logo.svg +336 -0
  69. common/static/common/img/brain.svg +1 -0
  70. common/templates/common/onetrust_cookies_consent_notice.html +6 -6
  71. common/tests/test_migration_anonymise_orphan_schools.py +30 -0
  72. common/tests/test_migration_anonymise_orphan_users.py +30 -0
  73. common/tests/test_migration_blocked_time.py +3 -11
  74. common/tests/test_migration_remove_teacher_title.py +1 -3
  75. common/tests/test_migration_unique_school_names.py +33 -0
  76. common/tests/test_migration_verify_returning_users.py +59 -0
  77. common/tests/test_models.py +49 -43
  78. common/tests/utils/classes.py +1 -3
  79. common/tests/utils/email.py +11 -49
  80. common/tests/utils/organisation.py +10 -14
  81. common/tests/utils/student.py +14 -67
  82. common/tests/utils/teacher.py +16 -38
  83. common/tests/utils/user.py +1 -3
  84. cfl_common-5.3.0.dist-info/METADATA +0 -20
  85. cfl_common-5.3.0.dist-info/RECORD +0 -48
  86. common/email_messages.py +0 -218
  87. common/fixtures/unlock_worksheet3.json +0 -20
  88. common/fixtures/worksheets.json +0 -98
  89. common/fixtures/worksheets2.json +0 -110
  90. common/tests/test_migration_aimmo_characters.py +0 -31
  91. common/tests/test_migration_worksheets.py +0 -49
  92. {cfl_common-5.3.0.dist-info → cfl_common-8.9.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: cfl-common
3
+ Version: 8.9.15
4
+ Classifier: Programming Language :: Python :: 3
5
+ Classifier: Operating System :: OS Independent
6
+ Requires-Dist: asgiref==3.11.0; python_version >= "3.9"
7
+ Requires-Dist: certifi==2026.1.4; python_version >= "3.7"
8
+ Requires-Dist: cffi==2.0.0; platform_python_implementation != "PyPy"
9
+ Requires-Dist: charset-normalizer==3.4.4; python_version >= "3.7"
10
+ Requires-Dist: cryptography==44.0.1; python_version >= "3.7" and python_full_version not in "3.9.0, 3.9.1"
11
+ Requires-Dist: diff-match-patch==20241021; python_version >= "3.7"
12
+ Requires-Dist: django==5.1.15; python_version >= "3.10"
13
+ Requires-Dist: django-countries==7.6.1
14
+ Requires-Dist: django-csp==3.8
15
+ Requires-Dist: django-formtools==2.5.1; python_version >= "3.8"
16
+ Requires-Dist: django-import-export==4.2.0; python_version >= "3.9"
17
+ Requires-Dist: django-otp==1.7.0; python_version >= "3.8"
18
+ Requires-Dist: django-phonenumber-field==8.4.0; python_version >= "3.10"
19
+ Requires-Dist: django-pipeline==4.0.0; python_version >= "3.9"
20
+ Requires-Dist: django-two-factor-auth==1.17.0; python_version >= "3.8"
21
+ Requires-Dist: djangorestframework==3.16.0; python_version >= "3.9"
22
+ Requires-Dist: idna==3.11; python_version >= "3.8"
23
+ Requires-Dist: libsass==0.23.0; python_version >= "3.8"
24
+ Requires-Dist: more-itertools==8.7.0; python_version >= "3.5"
25
+ Requires-Dist: numpy==2.4.1; python_version >= "3.11"
26
+ Requires-Dist: pandas==2.3.3; python_version >= "3.9"
27
+ Requires-Dist: pgeocode==0.4.0; python_version >= "3.8"
28
+ Requires-Dist: pycparser==2.23; implementation_name != "PyPy"
29
+ Requires-Dist: pyjwt==2.6.0; python_version >= "3.7"
30
+ Requires-Dist: pypng==0.20220715.0
31
+ Requires-Dist: python-dateutil==2.9.0.post0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2"
32
+ Requires-Dist: pytz==2025.2
33
+ Requires-Dist: qrcode==7.4.2; python_version >= "3.7"
34
+ Requires-Dist: requests==2.32.5; python_version >= "3.9"
35
+ Requires-Dist: setuptools==80.9.0; python_version >= "3.9"
36
+ Requires-Dist: six==1.17.0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2"
37
+ Requires-Dist: sqlparse==0.5.5; python_version >= "3.8"
38
+ Requires-Dist: tablib==3.7.0; python_version >= "3.9"
39
+ Requires-Dist: typing-extensions==4.15.0; python_version >= "3.9"
40
+ Requires-Dist: tzdata==2025.3; python_version >= "2"
41
+ Requires-Dist: urllib3==2.6.3; python_version >= "3.9"
42
+ Requires-Dist: wheel==0.45.1; python_version >= "3.8"
43
+ Dynamic: classifier
44
+ Dynamic: description
45
+ Dynamic: requires-dist
46
+
47
+ Common package for Code for Life
@@ -0,0 +1,99 @@
1
+ common/__init__.py,sha256=XlncBOpKp_gekbKH7Y_i6yu1qy5tJc3Y8sn8cDy-Vgk,48
2
+ common/app_settings.py,sha256=br31aXMTs48oyxkvGmCSoGb94Ir8imONuD2uNO3k7-k,2763
3
+ common/apps.py,sha256=49UXZ3bSkFKvIEOL4zM7y1sAhccQJyRtsoOg5XVd_8Y,129
4
+ common/context_processors.py,sha256=X0iuX5qu9kMWa7q8osE9CJ2LgM7pPOYQFGdjm8X3rk0,236
5
+ common/csp_config.py,sha256=saeg9LbRr5xw7NDJPlt6fqi8Zz0vI8Rpc4VCS6oJNe8,2976
6
+ common/mail.py,sha256=pIRfUMVoJWxdv74UqToj_0_pTVTC51z6QlFVLI3QBOw,6874
7
+ common/models.py,sha256=Qm-UHUR4Qbjn407HbA-YPFHQQk0qOZAsylukptnBXq0,19149
8
+ common/permissions.py,sha256=gC6RQGZI2QDBbglx-xr_V4Hl2C2nf1V2_uPmEuoEcJo,2416
9
+ common/utils.py,sha256=Nn2Npao9Uqad5Js_IdHwF-ow6wrPNpBLW4AO1LxoEBc,1727
10
+ common/fixtures/aimmo_characters.json,sha256=LqjwI05-H4heSBxl6_hS-nb3gMN_4SNVlDnDRT6qNZ8,1234
11
+ common/fixtures/aimmo_characters2.json,sha256=R-23mbjLrvpH4G9khXKcu7PTDK86xf9eHf2HfFTp6us,1285
12
+ common/fixtures/aimmo_characters3.json,sha256=7Pv_6DFastPzmM86sPx6D60Y8Biq84GLL5pWz5NGSUA,1392
13
+ common/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ common/helpers/data_migration_loader.py,sha256=_BhS5lPmhcuVUbryBmJytlWdHyT02KYyxPkHar32mOE,1748
15
+ common/helpers/emails.py,sha256=wBgwTsOQSDIEFGZ3SS4N5XZO9nlwuCVzsjvgH4NNUkc,12060
16
+ common/helpers/generators.py,sha256=kTL5e91I8wgmjJ-mu4jr9vIacjccUZ5pZSAz5cUNhdM,1505
17
+ common/helpers/organisation.py,sha256=e-JKumKoXrkMTzZPv0H4ViWL8vtCt7oXJjn_zZ1ec00,427
18
+ common/migrations/0001_initial.py,sha256=Y2kt2xmdCbrmDXCgqmhXeacicNg26Zj7L7SANSsgAAI,9664
19
+ common/migrations/0002_emailverification.py,sha256=csWNasKNB5HQfrg5Owa6ovwx9f-v3ved-1B6QSu2_3s,2094
20
+ common/migrations/0003_aimmocharacter.py,sha256=ZS_-sJCVUnFdhDjyH75P5bryg5QKHPDfe-SXXK7k9KM,922
21
+ common/migrations/0004_add_aimmocharacters.py,sha256=543WKEphsvdKo8Z7f8wPgZHGxRPWMdo288O5_7edawo,430
22
+ common/migrations/0005_add_worksheets.py,sha256=gM-5yJQ-0r3Plrv__agri5JD5f5pqRf-fuvxYg9RrQw,243
23
+ common/migrations/0006_update_aimmo_character_image_path.py,sha256=De1d02dAYE2KT8uW1qPi0NmWp45_zXVNH7kjWg3f2ko,431
24
+ common/migrations/0007_add_pdf_names_to_first_two_worksheets.py,sha256=XxAVaQpwwst2L5Bh6EuNBwA_jtc04ULwtDY6SNMM46k,257
25
+ common/migrations/0008_unlock_worksheet_3.py,sha256=WzTdGbSjYNlyxNLVRMPWOhNBkR5e-lRewu0xBy5d69c,345
26
+ common/migrations/0009_add_blocked_time_to_teacher_and_student.py,sha256=hdff316HkAVCB0EW61qbR2lxwkxSTsD7OBK66PLBUUQ,599
27
+ common/migrations/0010_remove_teacher_title.py,sha256=dMX-wgD-nzRx2AmrvuLMtb1X7TIv1gZ9icacFgI1LNc,396
28
+ common/migrations/0011_student_login_id.py,sha256=0sMdbzshOu_hT3s7uC0ILKd4PA1waw14y83Re736788,400
29
+ common/migrations/0012_usersession.py,sha256=xmW1hqECQsJw9fKZ-GfwEIhNfdTtOnnq4xiu9ODw4zk,1135
30
+ common/migrations/0013_class_school.py,sha256=n5slnrrOFnrBsjAmkdcRxIUIXOXClHMjuCoDAJrYXAE,1142
31
+ common/migrations/0014_login_type.py,sha256=_liGPnErUKWj2hfErZjkw--2BM8pZCYIvdg96uJts08,817
32
+ common/migrations/0015_dailyactivity.py,sha256=jbzA7hwcEd7mg-w0he-OMpVGSUrjYuWW_QFXY2RWzjk,901
33
+ common/migrations/0016_joinreleasestudent.py,sha256=bu7s-artUHMRPxP0Rnbw10cQy47c2_GYOD8fzzHgXQ8,1208
34
+ common/migrations/0017_copy_email_to_username.py,sha256=oon4z_fHDxABJ-J3T3IeucAJPl2lYCu75zcZk0a1xfs,587
35
+ common/migrations/0018_update_aimmo_character_image_path.py,sha256=WKrxcjGjQ2pE4lcubkU37nsThmHbeVni9tCNSQWm8Sk,387
36
+ common/migrations/0019_aimmocharacter_alt.py,sha256=vhcO1-1TFNYJ2ILLj-tHq_z7jlhd9URwColHqTh11m8,418
37
+ common/migrations/0020_class_is_active_and_null_access_code.py,sha256=g0frY5T5AuVwCPIhj9UEtyB0lyMktl285eBJtLpN-zk,555
38
+ common/migrations/0021_school_is_active.py,sha256=S1HjZIalqLSbqrTu7AF0xvqZEbzcvLCCa1rMa7Pnc-w,736
39
+ common/migrations/0022_school_cleanup.py,sha256=r3YYnC6gJtBy5Ewa8_cjDxvK-W3oEm1IKopn-UXVyXg,661
40
+ common/migrations/0023_userprofile_aimmo_badges.py,sha256=NsOOw2XB03k4U5-2wDzuvN7P69IHLNKcjsPLMxmJbPM,515
41
+ common/migrations/0024_teacher_invited_by.py,sha256=UxsKaGB16y7NjH6mrqZceNLi3tERgLb7gxS14ozsTjw,632
42
+ common/migrations/0025_schoolteacherinvitation.py,sha256=Ba2gpIfeCkPGDnB6JqbM1DXlixkLqsbE3voKVK9Gvok,1819
43
+ common/migrations/0026_teacher_remove_join_request.py,sha256=U7hfnmNwQ0c6yzkiXhMrm2AdgrQszTjBal4U-v0H_VE,528
44
+ common/migrations/0027_class_created_by.py,sha256=H9T78SxvnrM0mjh5l_msa060MsJoWZ_bV-VizBElNpc,632
45
+ common/migrations/0028_coding_club_downloads.py,sha256=RLp7-M95MhwHCZfvo2qHfA_KZXa4pqXBni1Kaf26kOw,606
46
+ common/migrations/0029_dynamicelement.py,sha256=T48j7Uwik_H0bg8eFpSxB-PgxEfmPlPgrr19UFETrj4,684
47
+ common/migrations/0030_add_maintenance_banner.py,sha256=gZAVSbUPfZBTXHlJ_vjO4XwlAgIm6JcR59xZWawS4Ns,851
48
+ common/migrations/0031_improve_admin_panel.py,sha256=UAOBZUS5jR071ciQjO-CoEN6y4BJqMSD1YvYwJBd3FI,1665
49
+ common/migrations/0032_dailyactivity_level_control_submits.py,sha256=E6KiHkUXs1ka0SknETP_HXRTr1cKELPBIj5WgVdZNS8,417
50
+ common/migrations/0033_password_reset_tracking_fields.py,sha256=s2kqLCJBeAIeYJjdlRdXHlmNwZb7Czq7omJp51VKc8M,619
51
+ common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py,sha256=j3OKxJZTK4NQKVx2JkcK4o9Ie6C9yqbQHfZRsn4NIZg,438
52
+ common/migrations/0035_rename_lockout_fields.py,sha256=1UbvNJ1Qf2SNqGRRJCjXhxHi_rnJuToUW8DEF-tH0ZM,808
53
+ common/migrations/0036_rename_awaiting_email_verification_userprofile_is_verified.py,sha256=wmfENAwFqegcBJYk0wcFdgvY-m2BlGAFQjt-wNO6kBM,396
54
+ common/migrations/0037_migrate_email_verification.py,sha256=zC8rZ3xFhkbHqr3oUyTO2XHleqbx8o9wA2S_24_Y6kY,1018
55
+ common/migrations/0038_delete_emailverification.py,sha256=JTjGGrcJQY7sagMWLTn8jWP4Ldm99LwWo8Sn7QgfIgw,314
56
+ common/migrations/0039_copy_email_to_username.py,sha256=h2NwkcMJ1pBCVKtEj9spM72hG4zm0JnWKXkQI7i9p48,552
57
+ common/migrations/0040_school_county.py,sha256=LuPMnxLXOVZDlIeFtKr5wNrxBvVVrcjbnXyCjWgq4QQ,411
58
+ common/migrations/0041_populate_gb_counties.py,sha256=74pFXOqUcPh8fCyhlOGQNUd0yzfDCUDR-Y2aO6UyP_Y,898
59
+ common/migrations/0042_totalactivity.py,sha256=U8nY0lcnreU4ugWpt8xi8lSDDRDg3cnV7liYVU_MxNw,810
60
+ common/migrations/0043_add_total_activity.py,sha256=9dCx3-uCrmG5XS9snhTeFEOpaqFWZvjIvkgukYldZ4I,1065
61
+ common/migrations/0044_update_activity_models.py,sha256=9ZwggtsiMB8LzKQEoyeDSIaADbz_wFk55bt-C9wSooY,997
62
+ common/migrations/0045_otp.py,sha256=_GmCOFOINqFMBqPBvdBaR1nwAI_FkzIlMTq_kfaN1IQ,599
63
+ common/migrations/0046_alter_school_country.py,sha256=dg_lexw7ALB-jlOm_EBQauk9mI4VbqUGv0qQsHo0b5s,437
64
+ common/migrations/0047_delete_school_postcode.py,sha256=GPV0hLfXmbPpx4-G5OaaLy6aalKvSnZLH0aGggYx9u0,331
65
+ common/migrations/0048_unique_school_names.py,sha256=pu5xiuesvFNGngD-hl0OQ6Gi2r6pEY9fPCayKyb9n04,1433
66
+ common/migrations/0049_anonymise_orphan_users.py,sha256=tw9xMrDMRPDCO8HWjBVlnQF8r1YVCKZnVr2wZ3He6og,847
67
+ common/migrations/0050_anonymise_orphan_schools.py,sha256=_KCkSkoObTpLplX6gXvlV3JXpddn7neyJEa8YKFWeW0,869
68
+ common/migrations/0051_verify_returning_users.py,sha256=WMpoTA24WgimLEVmKXuPqZ3aZdClRhY5vuGtYseeJp0,758
69
+ common/migrations/0052_add_cse_fields.py,sha256=NhUkkcu2EBzJFhewCTccQ63AoANkGq1CXbFWIGJG9jk,2232
70
+ common/migrations/0053_clean_class_data.py,sha256=lBKlDa49YwT660o-Ot6IYe4I1KfervTn4uAijda0nyw,584
71
+ common/migrations/0054_delete_aimmo_models.py,sha256=fmn4mDdlHr5DhPbIl_ygvGwWVFD8TZHAgQ6VUQQgCx8,415
72
+ common/migrations/0055_alter_schoolteacherinvitation_token.py,sha256=lzPAMaI3zU_q25RuIos_LV97NXOa3MIn_eWaEL71Y4I,403
73
+ common/migrations/0056_set_non_school_teachers_as_non_admins.py,sha256=_BrC9yfSYpP-c7EGFZmz8a4Kx_SxnRhpLMxJ70RVFOY,603
74
+ common/migrations/0057_teacher_teacher__is_admin.py,sha256=4pinm9T3JF3PRNLnbXI6mdFiNyxg1MnRs8lMKC4S5Bc,511
75
+ common/migrations/0058_userprofile_google_refresh_token_and_more.py,sha256=xHBv29aWKGkISxhQd_ao5RcZPg5UkirsVf9sqajkk_8,656
76
+ common/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
+ common/static/common/img/RR_logo.svg,sha256=DjbNHUHWrYkyuefTsg3uSHFI9-kVHBndpaeznfPPcTw,557149
78
+ common/static/common/img/brain.svg,sha256=689wY5b7E40oKlGumLoHBRpV5z6zCcCp0sGrxjXToXU,16332
79
+ common/templates/common/freshdesk_widget.html,sha256=gc4BCbyh-ADCd0TkLYnT4X8FgOcJL_Bum-PSFXv3Vog,336
80
+ common/templates/common/onetrust_cookies_consent_notice.html,sha256=yrmLn-vbxkYUhaaAdJjefEhaSCbQBNsBb8ACIx4Hzpk,1077
81
+ common/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
+ common/tests/test_migration_anonymise_orphan_schools.py,sha256=wJRyPgRvBsXLSCFdbBi2GXjgSgDbKUTRiM31CXIvpqs,1194
83
+ common/tests/test_migration_anonymise_orphan_users.py,sha256=MGuI8YVvUReXxjK36i2n-vkC677I8HqVHph778zL34Q,1368
84
+ common/tests/test_migration_blocked_time.py,sha256=z9WxMTrZTKFieLfbQwkoOZozziPHmWVk6T4FysLeHGk,590
85
+ common/tests/test_migration_remove_teacher_title.py,sha256=wwm6tayb75QmDXwXBfxu6SIMf7Ant4rEHHEBLIFjHcI,522
86
+ common/tests/test_migration_unique_school_names.py,sha256=D5SQ1UmD8yHLiEDsA7mWl1O4HzzxsBN_RXErB3ikg5I,1032
87
+ common/tests/test_migration_verify_returning_users.py,sha256=n8JGW-TmE1Hv_4AHl3kn9b6Hwp7DkpZWiYkbPeR8PXw,2054
88
+ common/tests/test_models.py,sha256=xMdzonW5CADMjas_zfg8V1YPQpUetleyn6TE95hbO9k,3723
89
+ common/tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
+ common/tests/utils/classes.py,sha256=ZA2pp9Pyx3rwi0VFwtuUA2Pys9xQJ-L_zE0u2tpwEH4,1094
91
+ common/tests/utils/email.py,sha256=RljsVjIob4Uqi3O5YhP2ifqfc4cMcdP4Gv0EaL-sHXo,1780
92
+ common/tests/utils/organisation.py,sha256=vNgKFtU3VPcWRnZfh82yCS90PLAK1XTYJNIxGwfgUI4,966
93
+ common/tests/utils/student.py,sha256=GYOyd2VH6QXjjLzjCh4hpT86U5si2URlJJWZwlCVLrU,3846
94
+ common/tests/utils/teacher.py,sha256=KQ_NAl4yQqiX_zwcULQjkovc29JPhnkLR5Nk3Ljzbpg,2661
95
+ common/tests/utils/user.py,sha256=NvLzZLVP4jy5Hn1iztOYF_BTQ9WsbSmuWMEzGzhAsRU,919
96
+ cfl_common-8.9.15.dist-info/METADATA,sha256=T3AlBNWQDjp7QKxJHCviAKmbqjc5uclhdg0b9XF32Wk,2486
97
+ cfl_common-8.9.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
98
+ cfl_common-8.9.15.dist-info/top_level.txt,sha256=LOtYx8KZTmnxM_zLK4rwrcI3PRc40Ihwp5rgaQ-ceaI,7
99
+ cfl_common-8.9.15.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
common/app_settings.py CHANGED
@@ -3,9 +3,14 @@ from django.conf import settings
3
3
  # Email address to source notifications from
4
4
  EMAIL_ADDRESS = getattr(settings, "EMAIL_ADDRESS", "no-reply@codeforlife.education")
5
5
 
6
+ # Dotdigital authorization details
7
+ DOTDIGITAL_AUTH = getattr(settings, "DOTDIGITAL_AUTH", "")
8
+
6
9
  # Dotmailer URLs for adding users to the newsletter address book
7
10
  DOTMAILER_CREATE_CONTACT_URL = getattr(settings, "DOTMAILER_CREATE_CONTACT_URL", "")
8
- DOTMAILER_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_ADDRESS_BOOK_URL", "")
11
+ DOTMAILER_TEACHER_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_TEACHER_ADDRESS_BOOK_URL", "")
12
+ DOTMAILER_STUDENT_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_STUDENT_ADDRESS_BOOK_URL", "")
13
+ DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL", "")
9
14
 
10
15
  # Dotmailer username for API authentication
11
16
  DOTMAILER_USER = getattr(settings, "DOTMAILER_USER", "")
@@ -18,7 +23,16 @@ DOTMAILER_DEFAULT_PREFERENCES = getattr(settings, "DOTMAILER_DEFAULT_PREFERENCES
18
23
 
19
24
  # Dotmailer URL for getting a user by email
20
25
  DOTMAILER_GET_USER_BY_EMAIL_URL = getattr(
21
- settings, "DOTMAILER_GET_USER_BY_EMAIL_URL", ""
26
+ settings,
27
+ "DOTMAILER_GET_USER_BY_EMAIL_URL",
28
+ "",
29
+ )
30
+
31
+ # Dotmailer URL for deleting a contact by id
32
+ DOTMAILER_DELETE_USER_BY_ID_URL = getattr(
33
+ settings,
34
+ "DOTMAILER_DELETE_USER_BY_ID_URL",
35
+ "",
22
36
  )
23
37
 
24
38
  # Dotmailer URL for adding consent data to a user
@@ -28,12 +42,28 @@ DOTMAILER_PUT_CONSENT_DATA_URL = getattr(settings, "DOTMAILER_PUT_CONSENT_DATA_U
28
42
  DOTMAILER_SEND_CAMPAIGN_URL = getattr(settings, "DOTMAILER_SEND_CAMPAIGN_URL", "")
29
43
 
30
44
  # ID of the "Thanks for staying!" campaign in Dotmailer
31
- DOTMAILER_THANKS_FOR_STAYING_CAMPAIGN_ID = getattr(
32
- settings, "DOTMAILER_THANKS_FOR_STAYING_CAMPAIGN_ID", ""
33
- )
45
+ DOTMAILER_THANKS_FOR_STAYING_CAMPAIGN_ID = getattr(settings, "DOTMAILER_THANKS_FOR_STAYING_CAMPAIGN_ID", "")
46
+
47
+ # Fernet encryption for OAuth2 sign in
48
+ ENCRYPTION_KEY = getattr(settings, "ENCRYPTION_KEY", "")
34
49
 
35
50
  # The name of the google app engine service the application is running on, local otherwise
36
51
  MODULE_NAME = getattr(settings, "MODULE_NAME", "local")
37
52
 
38
53
  # Boolean indicating if OneTrust cookie management is enabled or not
39
54
  COOKIE_MANAGEMENT_ENABLED = getattr(settings, "COOKIE_MANAGEMENT_ENABLED", True)
55
+
56
+
57
+ def domain(request=None):
58
+ """Returns the full domain depending on whether it's local, dev, staging or prod."""
59
+ if hasattr(settings, "SERVICE_BASE_URL"):
60
+ return getattr(settings, "SERVICE_BASE_URL")
61
+
62
+ domain = "https://www.codeforlife.education"
63
+
64
+ if MODULE_NAME == "local":
65
+ domain = f"http://{request.get_host()}" if request is not None else "localhost:8000"
66
+ elif MODULE_NAME == "staging" or MODULE_NAME == "dev":
67
+ domain = f"https://{MODULE_NAME}-dot-decent-digit-629.appspot.com"
68
+
69
+ return domain
common/csp_config.py ADDED
@@ -0,0 +1,85 @@
1
+ """CSP Config"""
2
+
3
+ from .app_settings import domain, MODULE_NAME
4
+
5
+ CSP_DEFAULT_SRC = ("self",)
6
+ CSP_CONNECT_SRC = (
7
+ "'self'",
8
+ "https://*.onetrust.com/",
9
+ "https://api.pwnedpasswords.com",
10
+ "https://euc-widget.freshworks.com/",
11
+ "https://codeforlife.freshdesk.com/",
12
+ "https://api.iconify.design/",
13
+ "https://api.simplesvg.com/",
14
+ "https://api.unisvg.com/",
15
+ "https://www.google-analytics.com/",
16
+ "https://pyodide-cdn2.iodide.io/v0.15.0/full/",
17
+ "https://crowdin.com/",
18
+ )
19
+ CSP_FONT_SRC = ("'self'", "https://fonts.gstatic.com/", "https://fonts.googleapis.com/", "https://use.typekit.net/")
20
+ CSP_SCRIPT_SRC = (
21
+ "'self'",
22
+ "'unsafe-inline'",
23
+ "'unsafe-eval'",
24
+ "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js",
25
+ "https://cdn.crowdin.com/",
26
+ "https://*.onetrust.com/",
27
+ "https://code.jquery.com/",
28
+ "https://euc-widget.freshworks.com/",
29
+ "https://cdn-ukwest.onetrust.com/",
30
+ "https://code.iconify.design/2/2.0.3/iconify.min.js",
31
+ "https://www.googletagmanager.com/",
32
+ "https://www.recaptcha.net/",
33
+ "https://www.google.com/recaptcha/",
34
+ "https://www.gstatic.com/recaptcha/",
35
+ "https://use.typekit.net/mrl4ieu.js",
36
+ "https://pyodide-cdn2.iodide.io/v0.15.0/full/",
37
+ f"{domain()}/static/portal/",
38
+ f"{domain()}/static/common/",
39
+ )
40
+ CSP_STYLE_SRC = (
41
+ "'self'",
42
+ "'unsafe-inline'",
43
+ "https://euc-widget.freshworks.com/",
44
+ "https://cdn-ukwest.onetrust.com/",
45
+ "https://fonts.googleapis.com/",
46
+ "https://code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css",
47
+ "https://cdn.crowdin.com/",
48
+ f"{domain()}/static/portal/",
49
+ )
50
+ CSP_FRAME_SRC = (
51
+ "https://storage.googleapis.com/",
52
+ "https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/",
53
+ "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/",
54
+ "https://www.recaptcha.net/",
55
+ "https://www.google.com/recaptcha/",
56
+ "https://crowdin.com/",
57
+ f"{domain()}/static/common/img/",
58
+ f"{domain()}/static/game/image/",
59
+ )
60
+ CSP_IMG_SRC = (
61
+ "'self'",
62
+ "https://storage.googleapis.com/codeforlife-assets/images/",
63
+ "https://cdn-ukwest.onetrust.com/",
64
+ "https://p.typekit.net/",
65
+ "https://cdn.crowdin.com/",
66
+ "https://crowdin-static.downloads.crowdin.com/",
67
+ "data:",
68
+ f"{domain()}/static/portal/img/",
69
+ f"{domain()}/static/portal/static/portal/img/",
70
+ f"{domain()}/static/portal/img/",
71
+ f"{domain()}/favicon.ico",
72
+ f"{domain()}/img/",
73
+ f"{domain()}/account/two_factor/qrcode/",
74
+ f"{domain()}/static/",
75
+ f"{domain()}/static/game/image/",
76
+ f"{domain()}/static/game/raphael_image/",
77
+ f"{domain()}/static/game/js/blockly/media/",
78
+ f"{domain()}/static/icons/",
79
+ )
80
+ CSP_OBJECT_SRC = (f"{domain()}/static/common/img/", f"{domain()}/static/game/image/")
81
+ CSP_MEDIA_SRC = (
82
+ "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/",
83
+ f"{domain()}/static/game/sound/",
84
+ f"{domain()}/static/game/js/blockly/media/",
85
+ )
@@ -1,32 +1,32 @@
1
1
  [
2
- {
3
- "model": "common.aimmocharacter",
4
- "pk": 1,
5
- "fields": {
6
- "name": "Zayed",
7
- "description": "A pretty chill, curious soul that prefers practice to theory. Always ready to jump into an adventure if it looks interesting enough; not so much otherwise. Probably the one who accidentally turned the time machine on in first place.",
8
- "image_path": "images/Zayed.png",
9
- "sort_order": 300
10
- }
11
- },
12
- {
13
- "model": "common.aimmocharacter",
14
- "pk": 2,
15
- "fields": {
16
- "name": "Xian",
17
- "description": "Fun, active, will dance to just about anything that produces a beat. Has great memory, always a joke at hand, might try to introduce memes in Ancient Greece. Scored gold in a track race once and will take any opportunity to bring that up.",
18
- "image_path": "images/Xian.png",
19
- "sort_order": 100
20
- }
21
- },
22
- {
23
- "model": "common.aimmocharacter",
24
- "pk": 3,
25
- "fields": {
26
- "name": "Jools",
27
- "description": "A quick-witted kid who wasn\u2019t expecting to embark in a time-warping journey but can\u2019t say no to a challenge. Someone has to keep the rest of the group in check, after all!",
28
- "image_path": "images/Jools.png",
29
- "sort_order": 200
30
- }
2
+ {
3
+ "model": "common.aimmocharacter",
4
+ "pk": 1,
5
+ "fields": {
6
+ "name": "Zayed",
7
+ "description": "A pretty chill, curious soul that prefers practice to theory. Always ready to jump into an adventure if it looks interesting enough; not so much otherwise. Probably the one who accidentally turned the time machine on in first place.",
8
+ "image_path": "images/Zayed.png",
9
+ "sort_order": 300
31
10
  }
32
- ]
11
+ },
12
+ {
13
+ "model": "common.aimmocharacter",
14
+ "pk": 2,
15
+ "fields": {
16
+ "name": "Xian",
17
+ "description": "Fun, active, will dance to just about anything that produces a beat. Has great memory, always a joke at hand, might try to introduce memes in Ancient Greece. Scored gold in a track race once and will take any opportunity to bring that up.",
18
+ "image_path": "images/Xian.png",
19
+ "sort_order": 100
20
+ }
21
+ },
22
+ {
23
+ "model": "common.aimmocharacter",
24
+ "pk": 3,
25
+ "fields": {
26
+ "name": "Jools",
27
+ "description": "A quick-witted kid who wasn\u2019t expecting to embark in a time-warping journey but can\u2019t say no to a challenge. Someone has to keep the rest of the group in check, after all!",
28
+ "image_path": "images/Jools.png",
29
+ "sort_order": 200
30
+ }
31
+ }
32
+ ]
@@ -29,4 +29,4 @@
29
29
  "sort_order": 200
30
30
  }
31
31
  }
32
- ]
32
+ ]
@@ -0,0 +1,35 @@
1
+ [
2
+ {
3
+ "model": "common.aimmocharacter",
4
+ "pk": 1,
5
+ "fields": {
6
+ "name": "Zayed",
7
+ "description": "A pretty chill, curious soul that prefers practice to theory. Always ready to jump into an adventure if it looks interesting enough; not so much otherwise. Probably the one who accidentally turned the time machine on in the first place.",
8
+ "image_path": "images/aimmo_characters/Zayed.png",
9
+ "sort_order": 300,
10
+ "alt": "Illustration of Zayed"
11
+ }
12
+ },
13
+ {
14
+ "model": "common.aimmocharacter",
15
+ "pk": 2,
16
+ "fields": {
17
+ "name": "Xian",
18
+ "description": "Fun, active, will dance to just about anything that produces a beat. Has great memory, always a joke at hand, might try to introduce memes in Ancient Greece. Scored gold in a track race once and will take any opportunity to bring that up.",
19
+ "image_path": "images/aimmo_characters/Xian.png",
20
+ "sort_order": 100,
21
+ "alt": "Illustration of Xian"
22
+ }
23
+ },
24
+ {
25
+ "model": "common.aimmocharacter",
26
+ "pk": 3,
27
+ "fields": {
28
+ "name": "Jools",
29
+ "description": "A quick-witted kid who wasn't expecting to embark in a time-warping journey but can't say no to a challenge. Someone has to keep the rest of the group in check, after all!",
30
+ "image_path": "images/aimmo_characters/Jools.png",
31
+ "sort_order": 200,
32
+ "alt": "Illustration of Jools"
33
+ }
34
+ }
35
+ ]
@@ -10,7 +10,8 @@ def load_data_from_file(file_name) -> Callable:
10
10
  For use with migrations.RunPython
11
11
 
12
12
  Args:
13
- file_name (str): The name of the file containing the data you want to load. Include `.json` at the end. The file must be in the fixtures directory.
13
+ file_name (str): The name of the file containing the data you want to load. Include `.json` at the end.
14
+ The file must be in the fixtures directory.
14
15
  """
15
16
  absolute_file_path = Path(__file__).resolve().parent.parent / "fixtures" / file_name
16
17
 
@@ -26,9 +27,7 @@ def load_data_from_file(file_name) -> Callable:
26
27
  try:
27
28
  return apps.get_model(model_identifier)
28
29
  except (LookupError, TypeError):
29
- raise base.DeserializationError(
30
- "Invalid model identifier: '%s'" % model_identifier
31
- )
30
+ raise base.DeserializationError("Invalid model identifier: '%s'" % model_identifier)
32
31
 
33
32
  # Replace the _get_model() function on the module, so loaddata can utilize it.
34
33
  python._get_model = _get_model