Skip to content

Commit

Permalink
Merge branch 'master' into move-admin-given-and-revoked-emails
Browse files Browse the repository at this point in the history
  • Loading branch information
evemartin committed May 2, 2024
2 parents a76828f + dcbaa2f commit e241e2f
Show file tree
Hide file tree
Showing 17 changed files with 401 additions and 106 deletions.
96 changes: 48 additions & 48 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions cfl_common/common/migrations/0049_anonymise_orphan_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from django.apps.registry import Apps
from django.db import migrations

from portal.views.api import __anonymise_user


def anonymise_orphan_users(apps: Apps, *args):
"""
Users should never exist without a user-type linked to them. Anonymise all
instances of User objects without a Teacher or Student instance.
"""
User = apps.get_model("auth", "User")

active_orphan_users = User.objects.filter(
new_teacher__isnull=True, new_student__isnull=True, is_active=True
)

for active_orphan_user in active_orphan_users:
__anonymise_user(active_orphan_user)


class Migration(migrations.Migration):
dependencies = [("common", "0048_unique_school_names")]

operations = [
migrations.RunPython(
code=anonymise_orphan_users, reverse_code=migrations.RunPython.noop
),
]
30 changes: 30 additions & 0 deletions cfl_common/common/migrations/0050_anonymise_orphan_schools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from uuid import uuid4

from django.apps.registry import Apps
from django.db import migrations


def anonymise_orphan_schools(apps: Apps, *args):
"""
Schools without any teachers or students should be anonymised (inactive).
Mark all active orphan schools as inactive.
"""
School = apps.get_model("common", "School")

active_orphan_schools = School.objects.filter(teacher_school__isnull=True)

for active_orphan_school in active_orphan_schools:
active_orphan_school.name = uuid4().hex
active_orphan_school.is_active = False
active_orphan_school.save()


class Migration(migrations.Migration):
dependencies = [("common", "0049_anonymise_orphan_users")]

operations = [
migrations.RunPython(
code=anonymise_orphan_schools,
reverse_code=migrations.RunPython.noop,
),
]
30 changes: 30 additions & 0 deletions cfl_common/common/migrations/0051_verify_returning_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from django.apps.registry import Apps
from django.db import migrations


def verify_returning_users(apps: Apps, *args):
"""
Users cannot be unverified after having logged in at least once. Grab all
instances of unverified UserProfile where the User has logged in and mark it
as verified.
"""
UserProfile = apps.get_model("common", "UserProfile")

unverified_returning_userprofiles = UserProfile.objects.filter(
user__last_login__isnull=False, is_verified=False
)

for unverified_returning_userprofile in unverified_returning_userprofiles:
unverified_returning_userprofile.is_verified = True
unverified_returning_userprofile.save()


class Migration(migrations.Migration):
dependencies = [("common", "0050_anonymise_orphan_schools")]

operations = [
migrations.RunPython(
code=verify_returning_users,
reverse_code=migrations.RunPython.noop,
),
]
1 change: 0 additions & 1 deletion cfl_common/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from datetime import timedelta
from uuid import uuid4

import pgeocode
from django.contrib.auth.models import User
from django.db import models
from django.utils import timezone
Expand Down
30 changes: 30 additions & 0 deletions cfl_common/common/tests/test_migration_anonymise_orphan_schools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest
from django_test_migrations.migrator import Migrator


@pytest.mark.django_db
def test_migration_anonymise_orphan_schools(migrator: Migrator):
state = migrator.apply_initial_migration(
("common", "0049_anonymise_orphan_users")
)
User = state.apps.get_model("auth", "User")
UserProfile = state.apps.get_model("common", "UserProfile")
Teacher = state.apps.get_model("common", "Teacher")
School = state.apps.get_model("common", "School")

orphan_school = School.objects.create(name="OrphanSchool")
teacher_school = School.objects.create(name="TeacherSchool")

teacher_user = User.objects.create_user("TeacherUser", password="password")
teacher_userprofile = UserProfile.objects.create(user=teacher_user)
Teacher.objects.create(
user=teacher_userprofile, new_user=teacher_user, school=teacher_school
)

migrator.apply_tested_migration(("common", "0050_anonymise_orphan_schools"))

def assert_school_anonymised(pk: int, anonymised: bool):
assert School.objects.get(pk=pk).is_active != anonymised

assert_school_anonymised(orphan_school.pk, True)
assert_school_anonymised(teacher_school.pk, False)
30 changes: 30 additions & 0 deletions cfl_common/common/tests/test_migration_anonymise_orphan_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest
from django_test_migrations.migrator import Migrator


@pytest.mark.django_db
def test_migration_anonymise_orphan_users(migrator: Migrator):
state = migrator.apply_initial_migration(
("common", "0048_unique_school_names")
)
User = state.apps.get_model("auth", "User")
UserProfile = state.apps.get_model("common", "UserProfile")
Teacher = state.apps.get_model("common", "Teacher")
Student = state.apps.get_model("common", "Student")

orphan_user = User.objects.create_user("OrphanUser", password="password")
teacher_user = User.objects.create_user("TeacherUser", password="password")
student_user = User.objects.create_user("StudentUser", password="password")
teacher_userprofile = UserProfile.objects.create(user=teacher_user)
student_userprofile = UserProfile.objects.create(user=student_user)
Teacher.objects.create(user=teacher_userprofile, new_user=teacher_user)
Student.objects.create(user=student_userprofile, new_user=student_user)

migrator.apply_tested_migration(("common", "0049_anonymise_orphan_users"))

def assert_user_anonymised(pk: int, anonymised: bool):
assert User.objects.get(pk=pk).is_active != anonymised

assert_user_anonymised(orphan_user.pk, True)
assert_user_anonymised(teacher_user.pk, False)
assert_user_anonymised(student_user.pk, False)
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@


@pytest.mark.django_db
def test_0048_unique_school_names(migrator: Migrator):
state = migrator.apply_initial_migration(("common", "0047_delete_school_postcode"))
def test_migration_unique_school_names(migrator: Migrator):
state = migrator.apply_initial_migration(
("common", "0047_delete_school_postcode")
)
School = state.apps.get_model("common", "School")

school_name = "ExampleSchool"
Expand All @@ -15,7 +17,9 @@ def test_0048_unique_school_names(migrator: Migrator):
School(name=f"{school_name} 1"),
]
)
school_ids = list(School.objects.order_by("-id")[:3].values_list("id", flat=True))
school_ids = list(
School.objects.order_by("-id")[:3].values_list("id", flat=True)
)
school_ids.reverse()

migrator.apply_tested_migration(("common", "0048_unique_school_names"))
Expand Down
Loading

0 comments on commit e241e2f

Please sign in to comment.