feat(accounts): Add a mechanism to automatically change the local username when creating or deleting translations

This commit is contained in:
Tom Hubrecht 2024-09-26 13:29:36 +02:00
parent 941f2b031e
commit b33f13db30
Signed by: thubrecht
SSH key fingerprint: SHA256:r+nK/SIcWlJ0zFZJGHtlAoRwq1Rm+WcKAm5ADYMoQPc

View file

@ -2,9 +2,12 @@ from dataclasses import dataclass
from functools import cached_property from functools import cached_property
from typing import Optional, Self from typing import Optional, Self
from allauth.socialaccount.models import SocialAccount
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.http import HttpRequest from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from kanidm.exceptions import NoMatchingEntries from kanidm.exceptions import NoMatchingEntries
@ -84,17 +87,47 @@ class Translation(models.Model):
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.cas_login}{self.username}" return f"{self.cas_login}{self.username}"
def save(self, **kwargs) -> None: # pyright: ignore def save(self, *args, **kwargs) -> None:
# INFO: Only update the model if it does not already exist # INFO: Only update the model if it does not already exist
# This will prevent a lot of pain # This will prevent a lot of pain
if self.pk is None: if self.pk is None:
return super().save(**kwargs) try:
# Find out if a user exists with the cas_login to update
account = SocialAccount.objects.get(
provider="ens_cas", uid=self.cas_login
)
account.user.username = self.username
account.user.save()
# TODO: Update the distant kanidm data
except SocialAccount.DoesNotExist:
# No user has registered with this cas_login yet
pass
return super().save(*args, **kwargs)
class Meta: # pyright: ignore class Meta: # pyright: ignore
verbose_name = _("Correspondance de login") verbose_name = _("Correspondance de login")
verbose_name_plural = _("Correspondances de login") verbose_name_plural = _("Correspondances de login")
# INFO: We need to use a signal receiver here, as the delete method is not called
# when deleteing objects from the admin interface
@receiver(pre_delete, sender=Translation)
def restore_username(**kwargs):
"""
Restore the username to the cas_login
"""
cas_login = kwargs["instance"].cas_login
try:
account = SocialAccount.objects.get(provider="ens_cas", uid=cas_login)
account.user.username = cas_login
account.user.save()
except SocialAccount.DoesNotExist:
# No user has registered with this cas_login yet
pass
@dataclass @dataclass
class KanidmProfile: class KanidmProfile:
person: Person person: Person