Skip to content

Commit

Permalink
🏷️ Add more type annotations
Browse files Browse the repository at this point in the history
Made the solo config mixin a generic so that subclasses can
provide more narrow type annotations.
  • Loading branch information
sergei-maertens committed Feb 7, 2024
1 parent 915a195 commit 3fb1b3c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 21 deletions.
33 changes: 19 additions & 14 deletions mozilla_django_oidc_db/backends.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fnmatch
import logging
from typing import Any, Dict
from typing import Any, TypeVar, cast

from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
Expand All @@ -12,14 +12,16 @@
)

from .mixins import GetAttributeMixin, SoloConfigMixin
from .models import UserInformationClaimsSources
from .models import OpenIDConnectConfig, UserInformationClaimsSources
from .utils import obfuscate_claims

logger = logging.getLogger(__name__)

T = TypeVar("T", bound=OpenIDConnectConfig)


class OIDCAuthenticationBackend(
GetAttributeMixin, SoloConfigMixin, _OIDCAuthenticationBackend
GetAttributeMixin, SoloConfigMixin[T], _OIDCAuthenticationBackend
):
"""
Modifies the default OIDCAuthenticationBackend to use a configurable claim
Expand Down Expand Up @@ -80,7 +82,7 @@ def authenticate(self, *args, **kwargs):

return super().authenticate(*args, **kwargs)

def get_user_instance_values(self, claims) -> Dict[str, Any]:
def get_user_instance_values(self, claims) -> dict[str, Any]:
"""
Map the names and values of the claims to the fields of the User model
"""
Expand Down Expand Up @@ -152,22 +154,25 @@ def update_user(self, user, claims):

return user

def update_user_superuser_status(self, user, claims):
def update_user_superuser_status(self, user, claims) -> None:
"""
Assigns superuser status to the user if the user is a member of at least one
specific group. Superuser status is explicitly removed if the user is not or
no longer member of at least one of these groups.
"""
groups_claim = self.config.groups_claim
superuser_group_names = self.config.superuser_group_names

if superuser_group_names:
claim_groups = glom(claims, groups_claim, default=[])
if set(superuser_group_names) & set(claim_groups):
user.is_superuser = True
else:
user.is_superuser = False
user.save()
# can't do an isinstance check here
superuser_group_names = cast(list[str], self.config.superuser_group_names)

if not superuser_group_names:
return

claim_groups = glom(claims, groups_claim, default=[])
if set(superuser_group_names) & set(claim_groups):
user.is_superuser = True
else:
user.is_superuser = False
user.save()

def update_user_groups(self, user, claims):
"""
Expand Down
22 changes: 15 additions & 7 deletions mozilla_django_oidc_db/mixins.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
from typing import ClassVar, Generic, TypeVar, cast

from mozilla_django_oidc.utils import import_from_settings

from .models import OpenIDConnectConfig
from .models import OpenIDConnectConfig, OpenIDConnectConfigBase

T = TypeVar("T", bound=OpenIDConnectConfigBase)


class SoloConfigMixin:
config_class = OpenIDConnectConfig
class SoloConfigMixin(Generic[T]):
config_class: ClassVar[type[OpenIDConnectConfigBase]] = OpenIDConnectConfig
_solo_config: T

@property
def config(self):
def config(self) -> T:
if not hasattr(self, "_solo_config"):
self._solo_config = self.config_class.get_solo()
# django-solo and type checking is challenging, but a new release is on the
# way and should fix that :fingers_crossed:
config = self.config_class.get_solo()
self._solo_config = cast(T, config)
return self._solo_config

def refresh_config(self):
def refresh_config(self) -> None:
"""
Refreshes the cached config on the instance, required for middleware
since middleware is only instantiated once (during the Django startup phase)
Expand All @@ -34,7 +42,7 @@ def get_settings(self, attr, *args):


class GetAttributeMixin:
def __getattribute__(self, attr):
def __getattribute__(self, attr: str):
"""
Mixin used to avoid calls to the config model on __init__ and instead
do these calls runtime
Expand Down

0 comments on commit 3fb1b3c

Please sign in to comment.