Skip to content

Commit

Permalink
fix: anonymize user (#90)
Browse files Browse the repository at this point in the history
* fix: initialize custom request

* fix: add missing imports

* fix: request type hint

* fix: inherit proxy types
  • Loading branch information
SKairinos authored Feb 21, 2024
1 parent cd70f4f commit 45eba67
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 196 deletions.
58 changes: 57 additions & 1 deletion codeforlife/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@
from django.http import HttpRequest as _HttpRequest
from rest_framework.request import Request as _Request

from .user.models import User
from .user.models import (
AdminSchoolTeacherUser,
IndependentUser,
NonAdminSchoolTeacherUser,
NonSchoolTeacherUser,
SchoolTeacherUser,
StudentUser,
TeacherUser,
User,
)
from .user.models.session import SessionStore


Expand All @@ -32,3 +41,50 @@ class HttpRequest(_HttpRequest):
class Request(_Request):
session: SessionStore
user: t.Union[User, AnonymousUser]

@property
def anon_user(self):
"""The anonymous user that made the request."""
return t.cast(AnonymousUser, self.user)

@property
def auth_user(self):
"""The authenticated user that made the request."""
return t.cast(User, self.user)

@property
def teacher_user(self):
"""The authenticated teacher-user that made the request."""
return self.auth_user.as_type(TeacherUser)

@property
def school_teacher_user(self):
"""The authenticated school-teacher-user that made the request."""
return self.auth_user.as_type(SchoolTeacherUser)

@property
def admin_school_teacher_user(self):
"""The authenticated admin-school-teacher-user that made the request."""
return self.auth_user.as_type(AdminSchoolTeacherUser)

@property
def non_admin_school_teacher_user(self):
"""
The authenticated non-admin-school-teacher-user that made the request.
"""
return self.auth_user.as_type(NonAdminSchoolTeacherUser)

@property
def non_school_teacher_user(self):
"""The authenticated non-school-teacher-user that made the request."""
return self.auth_user.as_type(NonSchoolTeacherUser)

@property
def student_user(self):
"""The authenticated student-user that made the request."""
return self.auth_user.as_type(StudentUser)

@property
def indy_user(self):
"""The authenticated independent-user that made the request."""
return self.auth_user.as_type(IndependentUser)
92 changes: 0 additions & 92 deletions codeforlife/serializers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,10 @@

import typing as t

from django.contrib.auth.models import AnonymousUser
from django.views import View
from rest_framework.serializers import BaseSerializer as _BaseSerializer

from ..request import Request
from ..user.models import ( # TODO: add IndependentUser
AdminSchoolTeacherUser,
IndependentUser,
NonAdminSchoolTeacherUser,
NonSchoolTeacherUser,
SchoolTeacherUser,
StudentUser,
TeacherUser,
User,
)


# pylint: disable-next=abstract-method
Expand All @@ -34,87 +23,6 @@ def request(self):

return t.cast(Request, self.context["request"])

@property
def request_user(self):
"""
The user that made the request.
Assumes the user has authenticated.
"""

return t.cast(User, self.request.user)

@property
def request_teacher_user(self):
"""
The teacher-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(TeacherUser, self.request.user)

@property
def request_school_teacher_user(self):
"""
The school-teacher-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(SchoolTeacherUser, self.request.user)

@property
def request_admin_school_teacher_user(self):
"""
The admin-school-teacher-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(AdminSchoolTeacherUser, self.request.user)

@property
def request_non_admin_school_teacher_user(self):
"""
The non-admin-school-teacher-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(NonAdminSchoolTeacherUser, self.request.user)

@property
def request_non_school_teacher_user(self):
"""
The non-school-teacher-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(NonSchoolTeacherUser, self.request.user)

@property
def request_student_user(self):
"""
The student-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(StudentUser, self.request.user)

@property
def request_indy_user(self):
"""
The independent-user that made the request.
Assumes the user has authenticated.
"""

return t.cast(IndependentUser, self.request.user)

@property
def request_anon_user(self):
"""
The user that made the request.
Assumes the user has not authenticated.
"""

return t.cast(AnonymousUser, self.request.user)

@property
def view(self):
"""The view that instantiated this serializer."""
Expand Down
33 changes: 29 additions & 4 deletions codeforlife/user/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,29 @@ def totp_provisioning_uri(self):
issuer_name="Code for Life",
)

def as_type(self, typed_user_class: t.Type["AnyTypedUser"]):
"""Convert this generic user to a typed user.
Args:
typed_user_class: The type of user to convert to.
Returns:
An instance of the typed user.
"""
return typed_user_class(
pk=self.pk,
first_name=self.first_name,
last_name=self.last_name,
username=self.username,
is_active=self.is_active,
email=self.email,
is_staff=self.is_staff,
date_joined=self.date_joined,
is_superuser=self.is_superuser,
password=self.password,
last_login=self.last_login,
)


AnyUser = t.TypeVar("AnyUser", bound=User)

Expand Down Expand Up @@ -138,7 +161,7 @@ def get_queryset(self):
return super().get_queryset().filter(new_teacher__school__isnull=False)


class SchoolTeacherUser(User):
class SchoolTeacherUser(TeacherUser):
"""A user that is a teacher in a school."""

teacher: SchoolTeacher
Expand All @@ -161,7 +184,8 @@ def get_queryset(self):
return super().get_queryset().filter(new_teacher__is_admin=True)


class AdminSchoolTeacherUser(User):
# pylint: disable-next=too-many-ancestors
class AdminSchoolTeacherUser(SchoolTeacherUser):
"""A user that is an admin-teacher in a school."""

teacher: AdminSchoolTeacher
Expand All @@ -184,7 +208,8 @@ def get_queryset(self):
return super().get_queryset().filter(new_teacher__is_admin=False)


class NonAdminSchoolTeacherUser(User):
# pylint: disable-next=too-many-ancestors
class NonAdminSchoolTeacherUser(SchoolTeacherUser):
"""A user that is a non-admin-teacher in a school."""

teacher: NonAdminSchoolTeacher
Expand All @@ -205,7 +230,7 @@ def get_queryset(self):
return super().get_queryset().filter(new_teacher__school__isnull=True)


class NonSchoolTeacherUser(User):
class NonSchoolTeacherUser(TeacherUser):
"""A user that is a teacher not in a school."""

teacher: NonSchoolTeacher
Expand Down
4 changes: 2 additions & 2 deletions codeforlife/user/views/klass.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ def get_permissions(self):

# pylint: disable-next=missing-function-docstring
def get_queryset(self):
user = self.request_user
user = self.request.auth_user
if user.student:
return Class.objects.filter(students=user.student)

user = self.request_school_teacher_user
user = self.request.school_teacher_user
if user.teacher.is_admin:
return Class.objects.filter(teacher__school=user.teacher.school)

Expand Down
4 changes: 2 additions & 2 deletions codeforlife/user/views/school.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ def get_permissions(self):

# pylint: disable-next=missing-function-docstring
def get_queryset(self):
user = self.request_user
user = self.request.auth_user
if user.student:
return School.objects.filter(
# TODO: should be user.student.school_id
id=user.student.class_field.teacher.school_id
)

user = self.request_school_teacher_user
user = self.request.school_teacher_user
return School.objects.filter(id=user.teacher.school_id)
4 changes: 2 additions & 2 deletions codeforlife/user/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class UserViewSet(ModelViewSet[User]):

# pylint: disable-next=missing-function-docstring
def get_queryset(self):
user = self.request_user
user = self.request.auth_user
if user.student:
if user.student.class_field is None:
return User.objects.filter(id=user.id)
Expand All @@ -33,7 +33,7 @@ def get_queryset(self):

return teachers | students

user = self.request_teacher_user
user = self.request.teacher_user
if user.teacher.school:
teachers = User.objects.filter(
new_teacher__school=user.teacher.school_id
Expand Down
2 changes: 2 additions & 0 deletions codeforlife/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
Created on 24/01/2024 at 13:07:38(+00:00).
"""

from .api import APIView
from .csrf import CookieView
from .model import ModelViewSet
Loading

0 comments on commit 45eba67

Please sign in to comment.