codeforlife-portal 7.4.8__tar.gz → 8.0.0__tar.gz

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 (559) hide show
  1. {codeforlife-portal-7.4.8/codeforlife_portal.egg-info → codeforlife-portal-8.0.0}/PKG-INFO +1 -1
  2. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0/codeforlife_portal.egg-info}/PKG-INFO +1 -1
  3. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/codeforlife_portal.egg-info/SOURCES.txt +2 -2
  4. codeforlife-portal-8.0.0/codeforlife_portal.egg-info/requires.txt +14 -0
  5. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/security.py +4 -5
  6. codeforlife-portal-8.0.0/portal/__init__.py +1 -0
  7. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/admin.py +26 -24
  8. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/play.py +2 -2
  9. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/registration.py +2 -2
  10. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/teach.py +2 -2
  11. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/decorators.py +18 -18
  12. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/password.py +52 -54
  13. {codeforlife-portal-7.4.8/portal/templates/captcha → codeforlife-portal-8.0.0/portal/templates/django_recaptcha}/includes/js_v2_invisible.html +3 -3
  14. {codeforlife-portal-7.4.8/portal/templates/captcha → codeforlife-portal-8.0.0/portal/templates/django_recaptcha}/widget_v2_invisible.html +2 -2
  15. codeforlife-portal-8.0.0/portal/templates/two_factor/core/login.html +70 -0
  16. codeforlife-portal-8.0.0/portal/templates/two_factor/core/setup.html +66 -0
  17. codeforlife-portal-8.0.0/portal/templates/two_factor/profile/profile.html +60 -0
  18. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_captcha_forms.py +2 -2
  19. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_middleware.py +32 -10
  20. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/urls.py +94 -88
  21. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/api.py +30 -16
  22. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/home.py +45 -15
  23. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/registration.py +3 -3
  24. codeforlife-portal-8.0.0/portal/views/two_factor/core.py +28 -0
  25. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/two_factor/profile.py +2 -2
  26. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/setup.py +6 -13
  27. codeforlife-portal-7.4.8/codeforlife_portal.egg-info/requires.txt +0 -21
  28. codeforlife-portal-7.4.8/portal/__init__.py +0 -1
  29. codeforlife-portal-7.4.8/portal/templates/two_factor/core/login.html +0 -63
  30. codeforlife-portal-7.4.8/portal/templates/two_factor/core/setup.html +0 -57
  31. codeforlife-portal-7.4.8/portal/templates/two_factor/profile/profile.html +0 -42
  32. codeforlife-portal-7.4.8/portal/views/two_factor/core.py +0 -25
  33. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/LICENSE.md +0 -0
  34. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/MANIFEST.in +0 -0
  35. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/README.md +0 -0
  36. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/codeforlife_portal.egg-info/dependency_links.txt +0 -0
  37. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/codeforlife_portal.egg-info/not-zip-safe +0 -0
  38. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/codeforlife_portal.egg-info/top_level.txt +0 -0
  39. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/__init__.py +0 -0
  40. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/captcha.py +0 -0
  41. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/__init__.py +0 -0
  42. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/admin_access.py +0 -0
  43. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/basicauth.py +0 -0
  44. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/exceptionlogging.py +0 -0
  45. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/screentime_warning.py +0 -0
  46. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/middleware/session_timeout.py +0 -0
  47. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/static/apple-touch-icon-120x120.png +0 -0
  48. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/static/apple-touch-icon-152x152.png +0 -0
  49. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/static/apple-touch-icon-180x180.png +0 -0
  50. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/static/apple-touch-icon-76x76.png +0 -0
  51. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/static/apple-touch-icon.png +0 -0
  52. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/static/robots.txt +0 -0
  53. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/templates/deploy/csrf_failure.html +0 -0
  54. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/deploy/views.py +0 -0
  55. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/app_settings.py +0 -0
  56. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/backends.py +0 -0
  57. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/beta.py +0 -0
  58. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/context_processors.py +0 -0
  59. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/__init__.py +0 -0
  60. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/admin.py +0 -0
  61. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/dotmailer.py +0 -0
  62. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/error_messages.py +0 -0
  63. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/invite_teacher.py +0 -0
  64. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/forms/organisation.py +0 -0
  65. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/handlers.py +0 -0
  66. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/__init__.py +0 -0
  67. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/captcha.py +0 -0
  68. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/ratelimit.py +0 -0
  69. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/regexes.py +0 -0
  70. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/helpers/request_handlers.py +0 -0
  71. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0001_squashed_0041_new_news.py +0 -0
  72. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0042_school_country.py +0 -0
  73. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0043_auto_20150430_0952.py +0 -0
  74. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0044_auto_20150430_0959.py +0 -0
  75. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0045_auto_20150430_1446.py +0 -0
  76. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0046_auto_20150723_1101.py +0 -0
  77. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0047_remove_userprofile_avatar.py +0 -0
  78. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0048_plural_management_frontnews.py +0 -0
  79. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0049_refactor_emailverifications.py +0 -0
  80. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0050_refactor_emailverifications_2.py +0 -0
  81. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0051_add_missing_ev_records.py +0 -0
  82. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0052_refactor_emailverifications_3.py +0 -0
  83. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0053_refactor_teacher_student_1.py +0 -0
  84. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0054_pending_join_request_can_be_blank.py +0 -0
  85. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0055_add_preview_user.py +0 -0
  86. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0056_remove_preview_user.py +0 -0
  87. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0057_delete_frontpagenews.py +0 -0
  88. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0058_move_to_common_models.py +0 -0
  89. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0059_move_email_verifications_to_common.py +0 -0
  90. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0060_delete_guardian.py +0 -0
  91. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0061_make_portaladmin_teacher.py +0 -0
  92. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/0062_verify_portaladmin.py +0 -0
  93. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/migrations/__init__.py +0 -0
  94. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/mixins/__init__.py +0 -0
  95. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/mixins/cron_mixin.py +0 -0
  96. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/models.py +0 -0
  97. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/permissions/__init__.py +0 -0
  98. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/permissions/is_cron_request_from_google.py +0 -0
  99. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/pipeline_compilers/__init__.py +0 -0
  100. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/pipeline_compilers/libsass_compiler.py +0 -0
  101. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  102. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.svg +0 -0
  103. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  104. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  105. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  106. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/10_years_anniversary.png +0 -0
  107. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/10x_logo.png +0 -0
  108. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/RR_logo_grass_background.png +0 -0
  109. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/RR_logo_green.svg +0 -0
  110. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/RR_logo_simple.png +0 -0
  111. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/about_us_cfl.jpg +0 -0
  112. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/about_us_hero.jpg +0 -0
  113. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/about_us_ocado.jpg +0 -0
  114. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/barefoot_logo.png +0 -0
  115. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/bcs_logo.png +0 -0
  116. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/clubs.png +0 -0
  117. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/coding_club_hero.jpg +0 -0
  118. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/coding_club_python_pack.png +0 -0
  119. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/colorboxImages/border.png +0 -0
  120. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/colorboxImages/controls.png +0 -0
  121. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/colorboxImages/loading.gif +0 -0
  122. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/colorboxImages/loading_background.png +0 -0
  123. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/colorboxImages/overlay.png +0 -0
  124. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/confirmation_tick.png +0 -0
  125. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/cross.png +0 -0
  126. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/dee.png +0 -0
  127. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/facebook.png +0 -0
  128. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/favicon.ico +0 -0
  129. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/get_involved_hero.png +0 -0
  130. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/gitbook.png +0 -0
  131. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/gitbook_space.png +0 -0
  132. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/github.png +0 -0
  133. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/github_hero.png +0 -0
  134. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/gla_logo.png +0 -0
  135. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/hamburger.png +0 -0
  136. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/help_and_support_hero.jpg +0 -0
  137. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/home_educate.png +0 -0
  138. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/home_educate_hero.jpg +0 -0
  139. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/home_learning_hero.jpg +0 -0
  140. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/home_play.png +0 -0
  141. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/home_play_hero.jpg +0 -0
  142. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/hope_logo.png +0 -0
  143. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/howe_dell_1.png +0 -0
  144. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/howe_dell_2.png +0 -0
  145. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/howe_dell_3.png +0 -0
  146. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icl_logo.png +0 -0
  147. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_controller.png +0 -0
  148. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_free.png +0 -0
  149. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_globe.png +0 -0
  150. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_piechart.png +0 -0
  151. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_step_by_step.png +0 -0
  152. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_tracking.png +0 -0
  153. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/icon_uk_flag.png +0 -0
  154. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/kirsty.png +0 -0
  155. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_cfl.png +0 -0
  156. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_cfl_powered.svg +0 -0
  157. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_cfl_reminder_cards.jpg +0 -0
  158. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_cfl_white_landscape.png +0 -0
  159. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_ocado.png +0 -0
  160. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_ocado_group.png +0 -0
  161. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_ocado_group.svg +0 -0
  162. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_ocado_group_white.svg +0 -0
  163. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/logo_python_den.svg +0 -0
  164. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/long_europe_map.png +0 -0
  165. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/mc_saatchi_logo.png +0 -0
  166. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/nigel.png +0 -0
  167. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/ocado-swirl.svg +0 -0
  168. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/oval_blue.svg +0 -0
  169. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/oval_pink.svg +0 -0
  170. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/oval_yellow.svg +0 -0
  171. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/paper_plane.png +0 -0
  172. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/phil.png +0 -0
  173. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/polygon_blue.svg +0 -0
  174. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/polygon_pink.svg +0 -0
  175. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/polygon_yellow.svg +0 -0
  176. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/pressure_cooker_logo.png +0 -0
  177. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/python_den.png +0 -0
  178. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/python_den_banner.svg +0 -0
  179. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rapid_router.png +0 -0
  180. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rapid_router_landing_hero.png +0 -0
  181. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rapidrouter.png +0 -0
  182. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/resources_hero.jpg +0 -0
  183. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/resources_montage.jpg +0 -0
  184. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/reuben.png +0 -0
  185. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rob.png +0 -0
  186. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rr_advanced.png +0 -0
  187. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rr_beginner.png +0 -0
  188. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/rr_intermediate.png +0 -0
  189. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/sadface.png +0 -0
  190. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/sharon_harrison.jpg +0 -0
  191. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/sian.png +0 -0
  192. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/teaching_resources_hero.jpg +0 -0
  193. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/ten_year_map_pin.svg +0 -0
  194. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/thumbnail_educate_rapid_router.png +0 -0
  195. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/thumbnail_educate_resources.png +0 -0
  196. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/thumbnail_intro_c4l.jpg +0 -0
  197. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/thumbnail_play_rapid_router.png +0 -0
  198. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/thumbnail_python_den.png +0 -0
  199. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/twitter.png +0 -0
  200. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/universities.png +0 -0
  201. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/img/wes.png +0 -0
  202. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/bootstrap.min.js +0 -0
  203. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/carouselCards.js +0 -0
  204. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/common.js +0 -0
  205. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/independentLogin.js +0 -0
  206. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/independentRegistration.js +0 -0
  207. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/join_create_game_toggle.js +0 -0
  208. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/jquery.placeholder.js +0 -0
  209. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/levelControl.js +0 -0
  210. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/lib/jquery-video-lightning.js +0 -0
  211. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/lib/jquery.colorbox.js +0 -0
  212. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/lib/jquery.easy-ticker.js +0 -0
  213. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/lib/jquery.min.js +0 -0
  214. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/lib/modernizr-build.js +0 -0
  215. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/lib/papaparse.min.js +0 -0
  216. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/organisation_manage.js +0 -0
  217. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/passwordStrength.js +0 -0
  218. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/play.js +0 -0
  219. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/resetPassword.js +0 -0
  220. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/riveted.min.js +0 -0
  221. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/school.js +0 -0
  222. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/sticky_subnav.js +0 -0
  223. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/studentLogin.js +0 -0
  224. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/teach_browser.js +0 -0
  225. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/teach_class.js +0 -0
  226. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/teacherEditStudent.js +0 -0
  227. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/teacherLogin.js +0 -0
  228. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/js/tenYearMap.js +0 -0
  229. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_alerts.scss +0 -0
  230. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_badges.scss +0 -0
  231. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_breadcrumbs.scss +0 -0
  232. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_button-groups.scss +0 -0
  233. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_buttons.scss +0 -0
  234. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_carousel.scss +0 -0
  235. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_close.scss +0 -0
  236. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_code.scss +0 -0
  237. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_component-animations.scss +0 -0
  238. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_dropdowns.scss +0 -0
  239. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_forms.scss +0 -0
  240. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_glyphicons.scss +0 -0
  241. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_grid.scss +0 -0
  242. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_input-groups.scss +0 -0
  243. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_jumbotron.scss +0 -0
  244. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_labels.scss +0 -0
  245. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_list-group.scss +0 -0
  246. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_media.scss +0 -0
  247. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_mixins.scss +0 -0
  248. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_modals.scss +0 -0
  249. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_navbar.scss +0 -0
  250. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_navs.scss +0 -0
  251. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_normalize.scss +0 -0
  252. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_pager.scss +0 -0
  253. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_pagination.scss +0 -0
  254. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_panels.scss +0 -0
  255. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_popovers.scss +0 -0
  256. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_print.scss +0 -0
  257. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_progress-bars.scss +0 -0
  258. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_responsive-embed.scss +0 -0
  259. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_responsive-utilities.scss +0 -0
  260. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_scaffolding.scss +0 -0
  261. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_tables.scss +0 -0
  262. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_theme.scss +0 -0
  263. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_thumbnails.scss +0 -0
  264. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_tooltip.scss +0 -0
  265. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_type.scss +0 -0
  266. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_utilities.scss +0 -0
  267. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_variables.scss +0 -0
  268. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/_wells.scss +0 -0
  269. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_alerts.scss +0 -0
  270. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_background-variant.scss +0 -0
  271. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_border-radius.scss +0 -0
  272. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_breakpoints.scss +0 -0
  273. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_buttons.scss +0 -0
  274. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_center-block.scss +0 -0
  275. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_clearfix.scss +0 -0
  276. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_forms.scss +0 -0
  277. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_gradients.scss +0 -0
  278. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_grid-framework.scss +0 -0
  279. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_grid.scss +0 -0
  280. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_hide-text.scss +0 -0
  281. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_image.scss +0 -0
  282. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_labels.scss +0 -0
  283. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_list-group.scss +0 -0
  284. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_nav-divider.scss +0 -0
  285. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_nav-vertical-align.scss +0 -0
  286. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_opacity.scss +0 -0
  287. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_pagination.scss +0 -0
  288. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_panels.scss +0 -0
  289. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_progress-bar.scss +0 -0
  290. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_reset-filter.scss +0 -0
  291. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_reset-text.scss +0 -0
  292. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_resize.scss +0 -0
  293. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_responsive-visibility.scss +0 -0
  294. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_size.scss +0 -0
  295. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_tab-focus.scss +0 -0
  296. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_table-row.scss +0 -0
  297. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_text-emphasis.scss +0 -0
  298. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_text-overflow.scss +0 -0
  299. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_text-truncate.scss +0 -0
  300. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap/mixins/_vendor-prefixes.scss +0 -0
  301. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap.scss +0 -0
  302. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_mixins/_all.scss +0 -0
  303. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_mixins/_border-radius.scss +0 -0
  304. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_mixins/_box-shadow.scss +0 -0
  305. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_mixins/_hover.scss +0 -0
  306. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_mixins/_nav-divider.scss +0 -0
  307. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_partials/_dropdown.scss +0 -0
  308. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_partials/_glyphicons.scss +0 -0
  309. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_partials/_grid.scss +0 -0
  310. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_partials/_variables.scss +0 -0
  311. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_align.scss +0 -0
  312. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_background.scss +0 -0
  313. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_borders.scss +0 -0
  314. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_clearfix.scss +0 -0
  315. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_cursor.scss +0 -0
  316. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_display.scss +0 -0
  317. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_flex.scss +0 -0
  318. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_float.scss +0 -0
  319. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_position.scss +0 -0
  320. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_screenreaders.scss +0 -0
  321. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_sizing.scss +0 -0
  322. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_spacing.scss +0 -0
  323. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_text.scss +0 -0
  324. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/bootstrap_utilities/_visibility.scss +0 -0
  325. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/colorbox.scss +0 -0
  326. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_all.scss +0 -0
  327. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_animation.scss +0 -0
  328. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_breakpoints.scss +0 -0
  329. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_card_constants.scss +0 -0
  330. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_colours.scss +0 -0
  331. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_homepage_constants.scss +0 -0
  332. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_levels.scss +0 -0
  333. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_mixins.scss +0 -0
  334. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/modules/_spacing.scss +0 -0
  335. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_banners.scss +0 -0
  336. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_base.scss +0 -0
  337. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_buttons.scss +0 -0
  338. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_carousel.scss +0 -0
  339. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_footer.scss +0 -0
  340. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_forms.scss +0 -0
  341. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_grids.scss +0 -0
  342. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_header.scss +0 -0
  343. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_images.scss +0 -0
  344. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_popup.scss +0 -0
  345. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_progress-bars.scss +0 -0
  346. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_subnavs.scss +0 -0
  347. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_tables.scss +0 -0
  348. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_text.scss +0 -0
  349. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_ui-dialog.scss +0 -0
  350. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/partials/_utils.scss +0 -0
  351. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/sass/styles.scss +0 -0
  352. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/static/portal/video/code for life .pdf +0 -0
  353. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/__init__.py +0 -0
  354. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/about.py +0 -0
  355. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/coding_club.py +0 -0
  356. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/help_and_support.py +0 -0
  357. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/home_learning.py +0 -0
  358. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/materials.py +0 -0
  359. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/play.py +0 -0
  360. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/teach.py +0 -0
  361. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/teacher_resources.py +0 -0
  362. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/strings/ten_year_map.py +0 -0
  363. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/403.html +0 -0
  364. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/404.html +0 -0
  365. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/500.html +0 -0
  366. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/email.html +0 -0
  367. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/email.txt +0 -0
  368. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/about.html +0 -0
  369. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/base.html +0 -0
  370. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/base_no_userprofile.html +0 -0
  371. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/coding_club.html +0 -0
  372. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/contribute.html +0 -0
  373. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/dotmailer_consent_form.html +0 -0
  374. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/email_invitation_sent.html +0 -0
  375. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/email_style_template.html +0 -0
  376. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/email_verification_failed.html +0 -0
  377. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/email_verification_needed.html +0 -0
  378. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/form_shapes.html +0 -0
  379. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/getinvolved.html +0 -0
  380. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/home.html +0 -0
  381. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/home_learning.html +0 -0
  382. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/locked_out.html +0 -0
  383. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/locked_out_school_student.html +0 -0
  384. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/login/independent_student.html +0 -0
  385. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/login/student.html +0 -0
  386. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/login/student_class_code.html +0 -0
  387. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/login/teacher.html +0 -0
  388. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/mouseflow.html +0 -0
  389. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/banner.html +0 -0
  390. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/benefits.html +0 -0
  391. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/card_list.html +0 -0
  392. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/character_list.html +0 -0
  393. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/delete_popup.html +0 -0
  394. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/donate_popup.html +0 -0
  395. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/footer.html +0 -0
  396. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/header.html +0 -0
  397. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/headline.html +0 -0
  398. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/hero_card.html +0 -0
  399. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/info_popup.html +0 -0
  400. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/invite_admin_teacher.html +0 -0
  401. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/popup.html +0 -0
  402. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/register_newsletter_tickbox.html +0 -0
  403. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/screentime_popup.html +0 -0
  404. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/service_unavailable_popup.html +0 -0
  405. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/session_popup.html +0 -0
  406. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/teacher_non_dashboard_subnav.html +0 -0
  407. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/partials/teacher_non_dashboard_subnav_account.html +0 -0
  408. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/play/student_dashboard.html +0 -0
  409. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/play/student_edit_account.html +0 -0
  410. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/play/student_join_organisation.html +0 -0
  411. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/play.html +0 -0
  412. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/privacy_notice.html +0 -0
  413. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/register.html +0 -0
  414. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/reset_password.html +0 -0
  415. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/reset_password_confirm.html +0 -0
  416. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/reset_password_done.html +0 -0
  417. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/reset_password_email_sent.html +0 -0
  418. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/tag_manager/tag_manager_body.html +0 -0
  419. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/tag_manager/tag_manager_head.html +0 -0
  420. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/base_registering.html +0 -0
  421. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/class.html +0 -0
  422. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/dashboard.html +0 -0
  423. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/invited.html +0 -0
  424. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/onboarding_classes.html +0 -0
  425. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/onboarding_print.html +0 -0
  426. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/onboarding_school.html +0 -0
  427. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/onboarding_students.html +0 -0
  428. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_add_external_student.html +0 -0
  429. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_added_external_student.html +0 -0
  430. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_dismiss_students.html +0 -0
  431. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_edit_class.html +0 -0
  432. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_edit_student.html +0 -0
  433. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_move_all_classes.html +0 -0
  434. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_move_students.html +0 -0
  435. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach/teacher_move_students_to_class.html +0 -0
  436. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/teach.html +0 -0
  437. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/ten_year_map.html +0 -0
  438. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/portal/terms.html +0 -0
  439. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/_base.html +0 -0
  440. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/_wizard_actions.html +0 -0
  441. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/_wizard_actions_enable_2fa.html +0 -0
  442. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/_wizard_actions_submit.html +0 -0
  443. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/_wizard_forms.html +0 -0
  444. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/_wizard_forms_token.html +0 -0
  445. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/backup_token.html +0 -0
  446. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/core/backup_tokens.html +0 -0
  447. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/core/setup_complete.html +0 -0
  448. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/profile/disable.html +0 -0
  449. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templates/two_factor/setup_wizard_token.html +0 -0
  450. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/__init__.py +0 -0
  451. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/app_tags.py +0 -0
  452. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/banner_tags.py +0 -0
  453. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/benefits_tags.py +0 -0
  454. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/card_list_tags.py +0 -0
  455. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/future.py +0 -0
  456. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/headline_tags.py +0 -0
  457. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/hero_card_tags.py +0 -0
  458. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/templatetags/table_tags.py +0 -0
  459. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/__init__.py +0 -0
  460. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/base_test.py +0 -0
  461. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/conftest.py +0 -0
  462. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/__init__.py +0 -0
  463. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_make_portaladmin_teacher.py +0 -0
  464. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_preview_user_remove.py +0 -0
  465. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_preview_users.py +0 -0
  466. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_remove_front_page_news.py +0 -0
  467. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_remove_guardian.py +0 -0
  468. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_use_common_models.py +0 -0
  469. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/migrations/test_migration_verify_portaladmin.py +0 -0
  470. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/__init__.py +0 -0
  471. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/__init__.py +0 -0
  472. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/admin/__init__.py +0 -0
  473. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/admin/admin_base_page.py +0 -0
  474. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/admin/admin_data_page.py +0 -0
  475. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/admin/admin_map_page.py +0 -0
  476. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/base_page.py +0 -0
  477. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/email_verification_needed_page.py +0 -0
  478. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/forbidden_page.py +0 -0
  479. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/game_page.py +0 -0
  480. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/home_page.py +0 -0
  481. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/independent_login_page.py +0 -0
  482. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/password_reset_form_page.py +0 -0
  483. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/password_reset_page.py +0 -0
  484. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/play/__init__.py +0 -0
  485. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/play/account_page.py +0 -0
  486. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/play/dashboard_page.py +0 -0
  487. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/play/join_school_or_club_page.py +0 -0
  488. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/play/play_base_page.py +0 -0
  489. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/play_page.py +0 -0
  490. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/resources_page.py +0 -0
  491. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/signup_page.py +0 -0
  492. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/student_login_class_code.py +0 -0
  493. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/student_login_page.py +0 -0
  494. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/__init__.py +0 -0
  495. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py +0 -0
  496. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py +0 -0
  497. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/class_page.py +0 -0
  498. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/dashboard_page.py +0 -0
  499. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/dismiss_students_page.py +0 -0
  500. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/edit_student_page.py +0 -0
  501. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/move_class_page.py +0 -0
  502. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/move_classes_page.py +0 -0
  503. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py +0 -0
  504. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/move_students_page.py +0 -0
  505. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/onboarding_classes_page.py +0 -0
  506. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py +0 -0
  507. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py +0 -0
  508. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/onboarding_students_page.py +0 -0
  509. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teach/teach_base_page.py +0 -0
  510. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/pageObjects/portal/teacher_login_page.py +0 -0
  511. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/selenium_test_case.py +0 -0
  512. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/snapshots/__init__.py +0 -0
  513. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/snapshots/snap_test_partials.py +0 -0
  514. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_2FA.py +0 -0
  515. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_admin.py +0 -0
  516. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_api.py +0 -0
  517. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_class.py +0 -0
  518. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_emails.py +0 -0
  519. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_global_forms.py +0 -0
  520. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_helper_methods.py +0 -0
  521. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_independent_student.py +0 -0
  522. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_invite_teacher.py +0 -0
  523. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_organisation.py +0 -0
  524. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_partials.py +0 -0
  525. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_ratelimit.py +0 -0
  526. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_school_student.py +0 -0
  527. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_security.py +0 -0
  528. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_teacher.py +0 -0
  529. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_teacher_student.py +0 -0
  530. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/test_views.py +0 -0
  531. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/utils/__init__.py +0 -0
  532. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/utils/classes.py +0 -0
  533. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/tests/utils/messages.py +0 -0
  534. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/__init__.py +0 -0
  535. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/about.py +0 -0
  536. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/admin.py +0 -0
  537. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/cron/__init__.py +0 -0
  538. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/cron/user.py +0 -0
  539. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/dotmailer.py +0 -0
  540. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/email.py +0 -0
  541. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/legal.py +0 -0
  542. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/login/__init__.py +0 -0
  543. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/login/independent_student.py +0 -0
  544. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/login/student.py +0 -0
  545. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/login/teacher.py +0 -0
  546. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/organisation.py +0 -0
  547. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/play_landing_page.py +0 -0
  548. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/student/__init__.py +0 -0
  549. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/student/edit_account_details.py +0 -0
  550. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/student/play.py +0 -0
  551. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/teach.py +0 -0
  552. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/teacher/__init__.py +0 -0
  553. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/teacher/dashboard.py +0 -0
  554. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/teacher/teach.py +0 -0
  555. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/two_factor/__init__.py +0 -0
  556. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/views/two_factor/form.py +0 -0
  557. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/portal/wsgi.py +0 -0
  558. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/pyproject.toml +0 -0
  559. {codeforlife-portal-7.4.8 → codeforlife-portal-8.0.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 7.4.8
3
+ Version: 8.0.0
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 7.4.8
3
+ Version: 8.0.0
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
@@ -349,8 +349,8 @@ portal/templates/404.html
349
349
  portal/templates/500.html
350
350
  portal/templates/email.html
351
351
  portal/templates/email.txt
352
- portal/templates/captcha/widget_v2_invisible.html
353
- portal/templates/captcha/includes/js_v2_invisible.html
352
+ portal/templates/django_recaptcha/widget_v2_invisible.html
353
+ portal/templates/django_recaptcha/includes/js_v2_invisible.html
354
354
  portal/templates/portal/about.html
355
355
  portal/templates/portal/base.html
356
356
  portal/templates/portal/base_no_userprofile.html
@@ -0,0 +1,14 @@
1
+ django-recaptcha==4.0.0
2
+ pyyaml==6.0.2
3
+ importlib-metadata==4.13.0
4
+ reportlab==3.6.13
5
+ django-formtools==2.5.1
6
+ django-otp==1.5.4
7
+ requests==2.32.2
8
+ django-treebeard==4.7.1
9
+ django-sekizai==4.1.0
10
+ django-classy-tags==4.1.0
11
+ phonenumbers==8.12.12
12
+ django-ratelimit==3.0.1
13
+ django-preventconcurrentlogins==0.8.2
14
+ setuptools==74.0.0
@@ -4,8 +4,8 @@ from django.middleware.security import SecurityMiddleware
4
4
  class CustomSecurityMiddleware(SecurityMiddleware):
5
5
  """
6
6
  Extends Django's Security Middleware.
7
- See https://docs.djangoproject.com/en/3.2/_modules/django/middleware/security/ for
8
- the source code, as well as https://docs.djangoproject.com/en/3.2/ref/middleware/#module-django.middleware.security
7
+ See https://docs.djangoproject.com/en/4.2/_modules/django/middleware/security/ for
8
+ the source code, as well as https://docs.djangoproject.com/en/4.2/ref/middleware/#module-django.middleware.security
9
9
  for docs on security middleware.
10
10
  """
11
11
 
@@ -13,10 +13,9 @@ class CustomSecurityMiddleware(SecurityMiddleware):
13
13
  """
14
14
  Extends the original security middleware to ensure the X-XSS-Protection header
15
15
  is set to 1.
16
+ https://docs.djangoproject.com/en/5.1/releases/4.0/#securitymiddleware-no-longer-sets-the-x-xss-protection-header
16
17
  """
17
18
  super().process_response(request, response)
18
-
19
- if self.xss_filter:
20
- response["X-XSS-Protection"] = "1"
19
+ response.headers.setdefault("X-XSS-Protection", "1; mode=block")
21
20
 
22
21
  return response
@@ -0,0 +1 @@
1
+ __version__ = "8.0.0"
@@ -12,7 +12,7 @@ from common.models import (
12
12
  UserProfile,
13
13
  )
14
14
  from django.contrib import admin
15
- from django.contrib.auth.admin import UserAdmin
15
+ from django.contrib.auth.admin import UserAdmin as _UserAdmin
16
16
  from django.contrib.auth.models import User
17
17
  from django.http import HttpResponse
18
18
  from import_export.admin import ExportActionMixin
@@ -172,38 +172,40 @@ class TotalActivityAdmin(admin.ModelAdmin, ExportActionMixin):
172
172
  return False
173
173
 
174
174
 
175
- def anonymise_user(user_admin, request, queryset):
176
- for user in queryset:
177
- anonymise(user)
175
+ _UserAdmin.list_display += ("date_joined", "id")
176
+ _UserAdmin.list_filter += ("date_joined",)
178
177
 
179
178
 
180
- def export_as_csv(self, request, queryset):
181
- meta = self.model._meta
182
- field_names = [
183
- field.name for field in meta.fields if field.name != "password"
184
- ]
179
+ class UserAdmin(_UserAdmin):
180
+ actions = ["anonymise_user", "export_as_csv"]
181
+ add_form = AdminUserCreationForm
182
+ change_password_form = AdminChangeUserPasswordForm
185
183
 
186
- response = HttpResponse(content_type="text/csv")
187
- response["Content-Disposition"] = "attachment; filename={}.csv".format(meta)
188
- writer = csv.writer(response)
184
+ def anonymise_user(self, request, queryset):
185
+ for user in queryset:
186
+ anonymise(user)
189
187
 
190
- writer.writerow(field_names)
191
- for obj in queryset:
192
- writer.writerow([getattr(obj, field) for field in field_names])
188
+ anonymise_user.short_description = "Anonymise selected users"
193
189
 
194
- return response
190
+ def export_as_csv(self, request, queryset):
191
+ meta = self.model._meta
192
+ field_names = [
193
+ field.name for field in meta.fields if field.name != "password"
194
+ ]
195
195
 
196
+ response = HttpResponse(content_type="text/csv")
197
+ response["Content-Disposition"] = "attachment; filename={}.csv".format(
198
+ meta
199
+ )
200
+ writer = csv.writer(response)
196
201
 
197
- anonymise_user.short_description = "Anonymise selected users"
198
- export_as_csv.short_description = "Export selected users data as CSV"
202
+ writer.writerow(field_names)
203
+ for obj in queryset:
204
+ writer.writerow([getattr(obj, field) for field in field_names])
199
205
 
206
+ return response
200
207
 
201
- UserAdmin.list_display += ("date_joined", "id")
202
- UserAdmin.list_filter += ("date_joined",)
203
- UserAdmin.add_form = AdminUserCreationForm
204
- UserAdmin.change_password_form = AdminChangeUserPasswordForm
205
- UserAdmin.actions.append(anonymise_user)
206
- UserAdmin.actions.append(export_as_csv)
208
+ export_as_csv.short_description = "Export selected users data as CSV"
207
209
 
208
210
 
209
211
  admin.site.register(Class, ClassAdmin)
@@ -1,8 +1,6 @@
1
1
  import re
2
2
  from datetime import timedelta, date
3
3
 
4
- from captcha.fields import ReCaptchaField
5
- from captcha.widgets import ReCaptchaV2Invisible
6
4
  from common.helpers.emails import send_verification_email
7
5
  from common.models import Class, Student, stripStudentName
8
6
  from common.permissions import logged_in_as_independent_student
@@ -10,6 +8,8 @@ from django import forms
10
8
  from django.contrib.auth import authenticate
11
9
  from django.contrib.auth.forms import AuthenticationForm
12
10
  from django.utils import timezone
11
+ from django_recaptcha.fields import ReCaptchaField
12
+ from django_recaptcha.widgets import ReCaptchaV2Invisible
13
13
 
14
14
  from portal.forms.error_messages import INVALID_LOGIN_MESSAGE
15
15
  from portal.helpers.password import PasswordStrength, form_clean_password
@@ -1,5 +1,3 @@
1
- from captcha.fields import ReCaptchaField
2
- from captcha.widgets import ReCaptchaV2Invisible
3
1
  from common.mail import campaign_ids, send_dotdigital_email
4
2
  from common.models import Student, Teacher
5
3
  from django import forms
@@ -10,6 +8,8 @@ from django.contrib.sites.shortcuts import get_current_site
10
8
  from django.urls import reverse_lazy
11
9
  from django.utils.encoding import force_bytes
12
10
  from django.utils.http import urlsafe_base64_encode
11
+ from django_recaptcha.fields import ReCaptchaField
12
+ from django_recaptcha.widgets import ReCaptchaV2Invisible
13
13
 
14
14
  from portal.helpers.password import PasswordStrength, form_clean_password
15
15
 
@@ -2,14 +2,14 @@ import itertools
2
2
  import re
3
3
  from builtins import map, range, str
4
4
 
5
- from captcha.fields import ReCaptchaField
6
- from captcha.widgets import ReCaptchaV2Invisible
7
5
  from common.helpers.emails import send_verification_email
8
6
  from common.models import Student, stripStudentName, UserSession, Teacher
9
7
  from django import forms
10
8
  from django.contrib.auth import authenticate
11
9
  from django.contrib.auth.forms import AuthenticationForm
12
10
  from django.contrib.auth.models import User
11
+ from django_recaptcha.fields import ReCaptchaField
12
+ from django_recaptcha.widgets import ReCaptchaV2Invisible
13
13
  from game.models import Episode
14
14
 
15
15
  from portal.forms.error_messages import INVALID_LOGIN_MESSAGE
@@ -1,28 +1,24 @@
1
1
  from __future__ import absolute_import
2
2
 
3
3
  import datetime
4
- import pytz
5
- import re
6
-
4
+ from functools import wraps
7
5
 
6
+ import pytz
8
7
  from common.models import Teacher, Student
9
8
  from django.contrib.auth import logout
10
9
  from django.shortcuts import render
11
- from functools import wraps
12
10
  from ratelimit import ALL, UNSAFE
13
11
 
14
12
  from portal.helpers.ratelimit import is_ratelimited
15
- from portal.templatetags.app_tags import is_logged_in
16
- from portal.views.registration import blocked_and_not_expired
17
- from portal.views.login import has_user_lockout_expired
18
- from portal.helpers.ratelimit import get_ratelimit_count_for_user
19
-
20
13
  from portal.helpers.request_handlers import get_access_code_from_request
14
+ from portal.templatetags.app_tags import is_logged_in
21
15
 
22
16
  __all__ = ["ratelimit"]
23
17
 
24
18
 
25
- def ratelimit(group=None, key=None, rate=None, method=ALL, block=False, is_teacher=True):
19
+ def ratelimit(
20
+ group=None, key=None, rate=None, method=ALL, block=False, is_teacher=True
21
+ ):
26
22
  """
27
23
  Ratelimit decorator, adding custom functionality to django-ratelimit's default
28
24
  decorator. On block, the user is logged out, redirected to the "locked out" page,
@@ -63,25 +59,29 @@ def ratelimit(group=None, key=None, rate=None, method=ALL, block=False, is_teach
63
59
 
64
60
  access_code = get_access_code_from_request(request)
65
61
  model_finder = model.objects.get
66
- # look for school student
67
- # if access code not found (AttributeError)
68
- # if student not found (IndexError)
69
- # move on to another try block
70
- # similar logic followed afterwards
62
+ # look for school student if access code not found
63
+ # (AttributeError) if student not found (IndexError) move
64
+ # on to another try block similar logic followed afterwards
71
65
  if access_code:
72
66
  user_to_lockout = model_finder(
73
67
  new_user__first_name=username,
74
68
  class_field__access_code=access_code, # extract the found text from regex
75
69
  )
76
- lockout_template = "portal/locked_out_school_student.html"
70
+ lockout_template = (
71
+ "portal/locked_out_school_student.html"
72
+ )
77
73
  # look for indy student or teacher
78
74
  else:
79
- user_to_lockout = model_finder(new_user__username=username)
75
+ user_to_lockout = model_finder(
76
+ new_user__username=username
77
+ )
80
78
  else:
81
79
  user_to_lockout = model.objects.get(new_user=request.user)
82
80
 
83
81
  if user_to_lockout:
84
- user_to_lockout.blocked_time = datetime.datetime.now(tz=pytz.utc)
82
+ user_to_lockout.blocked_time = datetime.datetime.now(
83
+ tz=pytz.utc
84
+ )
85
85
  user_to_lockout.save()
86
86
 
87
87
  if is_logged_in(request.user):
@@ -1,16 +1,14 @@
1
+ import hashlib
1
2
  import re
2
3
  from enum import Enum, auto
3
4
 
5
+ import requests
4
6
  from django import forms
5
7
  from django.contrib.auth import update_session_auth_hash
6
8
  from django.contrib.auth.hashers import PBKDF2PasswordHasher as ph
7
9
  from django.core.exceptions import ValidationError
8
10
 
9
11
 
10
- import hashlib
11
- import requests
12
-
13
-
14
12
  def is_password_pwned(password):
15
13
  # Create SHA1 hash of the password
16
14
  sha1_hash = hashlib.sha1(password.encode()).hexdigest()
@@ -41,56 +39,56 @@ class PasswordStrength(Enum):
41
39
  TEACHER = auto()
42
40
 
43
41
  def password_test(self, password):
44
- if self is PasswordStrength.STUDENT:
45
- minimum_password_length = 6
46
- # Make student password case insensitive
47
- password = password.lower()
48
- if password and not password_strength_test(
49
- password=password,
50
- minimum_password_length=minimum_password_length,
51
- upper=False,
52
- lower=False,
53
- numbers=False,
54
- special_char=False,
55
- ):
56
- raise forms.ValidationError(
57
- f"Password not strong enough, consider using at least {minimum_password_length} characters and making it hard to guess."
58
- )
59
- if is_password_pwned(password):
60
- raise forms.ValidationError("Password is too common, consider using a different password.")
61
-
62
- elif self is PasswordStrength.INDEPENDENT:
63
- minimum_password_length = 8
64
- if password and not password_strength_test(
65
- password=password,
66
- minimum_password_length=minimum_password_length,
67
- upper=True,
68
- lower=True,
69
- numbers=True,
70
- special_char=False,
71
- ):
72
- raise forms.ValidationError(
73
- f"Password not strong enough, consider using at least {minimum_password_length} characters, "
74
- "upper and lower case letters, and numbers and making it hard to guess."
75
- )
76
- if is_password_pwned(password):
77
- raise forms.ValidationError("Password is too common, consider using a different password.")
78
- else:
79
- minimum_password_length = 10
80
- if password and not password_strength_test(
81
- password=password,
82
- minimum_password_length=minimum_password_length,
83
- upper=True,
84
- lower=True,
85
- numbers=True,
86
- special_char=True,
87
- ):
88
- raise forms.ValidationError(
89
- f"Password not strong enough, consider using at least {minimum_password_length} characters, "
90
- "upper and lower case letters, numbers, special characters and making it hard to guess."
91
- )
92
- if is_password_pwned(password):
93
- raise forms.ValidationError("Password is too common, consider using a different password.")
42
+ if password:
43
+ if self is PasswordStrength.STUDENT:
44
+ minimum_password_length = 6
45
+ # Make student password case insensitive
46
+ password = password.lower()
47
+ if not password_strength_test(
48
+ password=password,
49
+ minimum_password_length=minimum_password_length,
50
+ upper=False,
51
+ lower=False,
52
+ numbers=False,
53
+ special_char=False,
54
+ ):
55
+ raise forms.ValidationError(
56
+ f"Password not strong enough, consider using at least {minimum_password_length} characters and making it hard to guess."
57
+ )
58
+ if is_password_pwned(password):
59
+ raise forms.ValidationError("Password is too common, consider using a different password.")
60
+ elif self is PasswordStrength.INDEPENDENT:
61
+ minimum_password_length = 8
62
+ if not password_strength_test(
63
+ password=password,
64
+ minimum_password_length=minimum_password_length,
65
+ upper=True,
66
+ lower=True,
67
+ numbers=True,
68
+ special_char=False,
69
+ ):
70
+ raise forms.ValidationError(
71
+ f"Password not strong enough, consider using at least {minimum_password_length} characters, "
72
+ "upper and lower case letters, and numbers and making it hard to guess."
73
+ )
74
+ if is_password_pwned(password):
75
+ raise forms.ValidationError("Password is too common, consider using a different password.")
76
+ else:
77
+ minimum_password_length = 10
78
+ if not password_strength_test(
79
+ password=password,
80
+ minimum_password_length=minimum_password_length,
81
+ upper=True,
82
+ lower=True,
83
+ numbers=True,
84
+ special_char=True,
85
+ ):
86
+ raise forms.ValidationError(
87
+ f"Password not strong enough, consider using at least {minimum_password_length} characters, "
88
+ "upper and lower case letters, numbers, special characters and making it hard to guess."
89
+ )
90
+ if is_password_pwned(password):
91
+ raise forms.ValidationError("Password is too common, consider using a different password.")
94
92
 
95
93
  return password
96
94
 
@@ -1,8 +1,8 @@
1
- {# This is adapted from django-recaptcha 2.0.5 to work on multiple reCAPTCHA's on the same page #}
2
- {# See verifyCaptcha_{{ widget_uuid}} for the edit #}
1
+ <!-- This is adapted from django-recaptcha 4.0.0 to work on multiple
2
+ reCAPTCHA's on the same page
3
+ See verifyCaptcha_{{ widget_uuid}} for the edit #} -->
3
4
  <script src="https://{{ recaptcha_domain }}/recaptcha/api.js{% if api_params %}?{{ api_params }}{% endif %}"></script>
4
5
  <script type="text/javascript">
5
-
6
6
  // Submit function to be called, after reCAPTCHA was successful.
7
7
  var onSubmit_{{ widget_uuid }} = function(token) {
8
8
  console.log("reCAPTCHA validated for 'data-widget-uuid=\"{{ widget_uuid }}\"'. Submitting form...")
@@ -1,5 +1,5 @@
1
- {# copied from django-recaptcha 2.0.5 #}
2
- {% include "captcha/includes/js_v2_invisible.html" %}
1
+ <!-- copied from django-recaptcha 4.0.0 -->
2
+ {% include "django_recaptcha/includes/js_v2_invisible.html" %}
3
3
  <div class="g-recaptcha"
4
4
  {% for name, value in widget.attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}
5
5
  >
@@ -0,0 +1,70 @@
1
+ {# Overriden the original "two_factor" template to remove extending base template and slightly adjust style #}
2
+
3
+ {% load i18n %}
4
+ {% load two_factor_tags %}
5
+
6
+ {% block extra_media %}
7
+ {{ form.media }}
8
+ {% endblock %}
9
+
10
+ {% block content %}
11
+
12
+ <section class="row mx-0">
13
+ <span class="oval-blue login-shape-left"></span>
14
+ <span class="polygon-yellow login-shape-right"></span>
15
+ <div class="form--login is-flex form--register--teacher">
16
+ <div class="form col-xs-12 col-sm-8 col-md-8 col-lg-9 center-block">
17
+ <h4>{% block title %}{% trans "Welcome" %}{% endblock %}</h4>
18
+
19
+ {% if wizard.steps.current == 'auth' %}
20
+ <p>{% blocktrans %}Enter your credentials.{% endblocktrans %}</p>
21
+ {% elif wizard.steps.current == 'token' %}
22
+ <p>{{ device|as_verbose_action }}</p>
23
+ {% elif wizard.steps.current == 'backup' %}
24
+ <p>{% blocktrans trimmed %}Use this form for entering backup tokens for logging in.
25
+ These tokens have been generated for you to print and keep safe. Please
26
+ enter one of these backup tokens to log into your account.{% endblocktrans %}</p>
27
+ {% endif %}
28
+
29
+ <form action="" method="post">
30
+ {% block main_form_content %}
31
+ {% csrf_token %}
32
+ {% include "two_factor/_wizard_forms.html" %}
33
+
34
+ {# hidden submit button to enable [enter] key #}
35
+ <input type="submit" value="" hidden />
36
+
37
+ {% if other_devices %}
38
+ <p>{% trans "Or, alternatively, use one of your other authentication methods:" %}</p>
39
+ <p>
40
+ {% for other in other_devices %}
41
+ <button name="challenge_device" value="{{ other.persistent_id }}"
42
+ class="btn btn-secondary btn-block" type="submit">
43
+ {{ other|as_action }}
44
+ </button>
45
+ {% endfor %}</p>
46
+ {% endif %}
47
+
48
+ {% include "two_factor/_wizard_actions.html" %}
49
+ {% endblock %}
50
+ </form>
51
+
52
+ {% block 'backup_tokens' %}
53
+ {% if backup_tokens %}
54
+ <hr>
55
+ <div class="backup_tokens_form">
56
+ <form action="" method="post">
57
+ {% csrf_token %}
58
+ <p>{% trans "As a last resort, you can use a backup token:" %}</p>
59
+ <p>
60
+ <button name="wizard_goto_step" type="submit" value="backup"
61
+ class="button button--primary">{% trans "Use Backup Token" %}</button>
62
+ </p>
63
+ </form>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </section>
68
+ {% endif %}
69
+ {% endblock %}
70
+ {% endblock %}
@@ -0,0 +1,66 @@
1
+ {# Overriding the original "two_factor" template #}
2
+
3
+ {% extends "two_factor/_base_focus.html" %}
4
+ {% load i18n %}
5
+
6
+ {% block extra_media %}
7
+ {{ form.media }}
8
+ {% endblock %}
9
+
10
+ {% block content %}
11
+ <h4>{% block title %}{% trans "Enable Two-Factor Authentication" %}{% endblock %}</h4>
12
+ {% if wizard.steps.current == 'welcome' %}
13
+ <p>{% blocktrans trimmed %}You are about to take your account security to the
14
+ next level. Follow the steps in this wizard to enable two-factor
15
+ authentication.{% endblocktrans %}</p>
16
+ {% elif wizard.steps.current == 'method' %}
17
+ <p>{% blocktrans trimmed %}Please select which authentication method you would
18
+ like to use.{% endblocktrans %}</p>
19
+ {% elif wizard.steps.current == 'generator' %}
20
+ <p>{% blocktrans trimmed %}To start using a token generator, please use your
21
+ smartphone to scan the QR code below. For example, use Google
22
+ Authenticator.{% endblocktrans %}</p>
23
+ <p><img src="{{ QR_URL }}" alt="QR Code" class="bg-white"/></p>
24
+ <p>{% blocktrans trimmed %}Alternatively you can use the following secret to
25
+ set up TOTP in your authenticator or password manager manually.{% endblocktrans %}</p>
26
+ <p>{% translate "TOTP Secret:" %} <a href="{{ otpauth_url }}">{{ secret_key }}</a></p>
27
+ <p>{% blocktrans %}Then, enter the token generated by the app.{% endblocktrans %}</p>
28
+
29
+ {% elif wizard.steps.current == 'sms' %}
30
+ <p>{% blocktrans trimmed %}Please enter the phone number you wish to receive the
31
+ text messages on. This number will be validated in the next step.
32
+ {% endblocktrans %}</p>
33
+ {% elif wizard.steps.current == 'call' %}
34
+ <p>{% blocktrans trimmed %}Please enter the phone number you wish to be called on.
35
+ This number will be validated in the next step. {% endblocktrans %}</p>
36
+ {% elif wizard.steps.current == 'validation' %}
37
+ {% if challenge_succeeded %}
38
+ {% if device.method == 'call' %}
39
+ <p>{% blocktrans trimmed %}We are calling your phone right now, please enter the
40
+ digits you hear.{% endblocktrans %}</p>
41
+ {% elif device.method == 'sms' %}
42
+ <p>{% blocktrans trimmed %}We sent you a text message, please enter the tokens we
43
+ sent.{% endblocktrans %}</p>
44
+ {% endif %}
45
+ {% else %}
46
+ <p class="alert alert-warning" role="alert">{% blocktrans trimmed %}We've
47
+ encountered an issue with the selected authentication method. Please
48
+ go back and verify that you entered your information correctly, try
49
+ again, or use a different authentication method instead. If the issue
50
+ persists, contact the site administrator.{% endblocktrans %}</p>
51
+ {% endif %}
52
+ {% elif wizard.steps.current == 'yubikey' %}
53
+ <p>{% blocktrans trimmed %}To identify and verify your YubiKey, please insert a
54
+ token in the field below. Your YubiKey will be linked to your
55
+ account.{% endblocktrans %}</p>
56
+ {% endif %}
57
+
58
+ <form action="" method="post">{% csrf_token %}
59
+ {% include "two_factor/_wizard_forms.html" %}
60
+
61
+ {# hidden submit button to enable [enter] key #}
62
+ <input type="submit" value="" hidden />
63
+
64
+ {% include "two_factor/_wizard_actions.html" %}
65
+ </form>
66
+ {% endblock %}
@@ -0,0 +1,60 @@
1
+ {% extends "two_factor/_base.html" %}
2
+ {% load i18n %}
3
+ {% load two_factor_tags %}
4
+
5
+ {% block content %}
6
+ <h1>{% block title %}{% trans "Account Security" %}{% endblock %}</h1>
7
+
8
+ {% if default_device %}
9
+ <p>{% blocktrans with primary=default_device|as_action %}Primary method: {{ primary }}{% endblocktrans %}</p>
10
+
11
+ {% if available_phone_methods %}
12
+ <h2>{% trans "Backup Phone Numbers" %}</h2>
13
+ <p>{% blocktrans trimmed %}If your primary method is not available, we are able to
14
+ send backup tokens to the phone numbers listed below.{% endblocktrans %}</p>
15
+ {% if backup_phones %}
16
+ <ul>
17
+ {% for phone in backup_phones %}
18
+ <li>
19
+ {{ phone|as_action }}
20
+ <form method="post" action="{% url 'two_factor:phone_delete' phone.id %}"
21
+ onsubmit="return confirm({% trans 'Are you sure?' %})">
22
+ {% csrf_token %}
23
+ <button class="btn btn-sm btn-warning"
24
+ type="submit">{% trans "Unregister" %}</button>
25
+ </form>
26
+ </li>
27
+ {% endfor %}
28
+ </ul>
29
+ {% endif %}
30
+ <p><a href="{% url 'two_factor:phone_create' %}"
31
+ class="btn btn-info">{% trans "Add Phone Number" %}</a></p>
32
+ {% endif %}
33
+
34
+ <h2>{% trans "Backup Tokens" %}</h2>
35
+ <p>
36
+ {% blocktrans trimmed %}If you don't have any device with you, you can access
37
+ your account using backup tokens.{% endblocktrans %}
38
+ {% blocktrans trimmed count counter=backup_tokens %}
39
+ You have only one backup token remaining.
40
+ {% plural %}
41
+ You have {{ counter }} backup tokens remaining.
42
+ {% endblocktrans %}
43
+ </p>
44
+ <p><a href="{% url 'two_factor:backup_tokens' %}"
45
+ class="btn btn-info">{% trans "Show Codes" %}</a></p>
46
+
47
+ <h3>{% trans "Disable Two-Factor Authentication" %}</h3>
48
+ <p>{% blocktrans trimmed %}However we strongly discourage you to do so, you can
49
+ also disable two-factor authentication for your account.{% endblocktrans %}</p>
50
+ <p><a class="btn btn-secondary" href="{% url 'two_factor:disable' %}">
51
+ {% trans "Disable Two-Factor Authentication" %}</a></p>
52
+ {% else %}
53
+ <p>{% blocktrans trimmed %}Two-factor authentication is not enabled for your
54
+ account. Enable two-factor authentication for enhanced account
55
+ security.{% endblocktrans %}</p>
56
+ <p><a href="{% url 'two_factor:setup' %}" class="btn btn-primary">
57
+ {% trans "Enable Two-Factor Authentication" %}</a>
58
+ </p>
59
+ {% endif %}
60
+ {% endblock %}
@@ -1,7 +1,7 @@
1
- from captcha.fields import ReCaptchaField
2
- from captcha.widgets import ReCaptchaV2Invisible
3
1
  from django import forms
4
2
  from django.test import TestCase
3
+ from django_recaptcha.fields import ReCaptchaField
4
+ from django_recaptcha.widgets import ReCaptchaV2Invisible
5
5
 
6
6
  from portal.helpers.captcha import is_captcha_in_form, remove_captcha_from_forms
7
7