diff options
author | 2020-09-18 03:33:35 +1000 | |
---|---|---|
committer | 2020-09-18 03:33:35 +1000 | |
commit | 357b20145b2784d9334b941fc25bcb8ce7b64c11 (patch) | |
tree | ccd446b4841ad69ae22fdc91f4c246823e0f811e /pydis_site/apps/home/signals.py | |
parent | Add new test for deleted message context log_url. (diff) | |
parent | Merge pull request #390 from python-discord/allow_blank_or_null_for_nominatio... (diff) |
Merge branch 'master' into admin-api-pages-improvements
# Conflicts:
# pydis_site/apps/api/admin.py
Diffstat (limited to 'pydis_site/apps/home/signals.py')
-rw-r--r-- | pydis_site/apps/home/signals.py | 88 |
1 files changed, 71 insertions, 17 deletions
diff --git a/pydis_site/apps/home/signals.py b/pydis_site/apps/home/signals.py index 9f286882..8af48c15 100644 --- a/pydis_site/apps/home/signals.py +++ b/pydis_site/apps/home/signals.py @@ -1,3 +1,4 @@ +from contextlib import suppress from typing import List, Optional, Type from allauth.account.signals import user_logged_in @@ -8,7 +9,7 @@ from allauth.socialaccount.signals import ( pre_social_login, social_account_added, social_account_removed, social_account_updated) from django.contrib.auth.models import Group, User as DjangoUser -from django.db.models.signals import post_save, pre_delete, pre_save +from django.db.models.signals import post_delete, post_save, pre_save from pydis_site.apps.api.models import User as DiscordUser from pydis_site.apps.staff.models import RoleMapping @@ -37,7 +38,7 @@ class AllauthSignalListener: def __init__(self): post_save.connect(self.user_model_updated, sender=DiscordUser) - pre_delete.connect(self.mapping_model_deleted, sender=RoleMapping) + post_delete.connect(self.mapping_model_deleted, sender=RoleMapping) pre_save.connect(self.mapping_model_updated, sender=RoleMapping) pre_social_login.connect(self.social_account_updated) @@ -133,13 +134,29 @@ class AllauthSignalListener: Processes deletion signals from the RoleMapping model, removing perms from users. We need to do this to ensure that users aren't left with permissions groups that - they shouldn't have assigned to them when a RoleMapping is deleted from the database. + they shouldn't have assigned to them when a RoleMapping is deleted from the database, + and to remove their staff status if they should no longer have it. """ instance: RoleMapping = kwargs["instance"] for user in instance.group.user_set.all(): + # Firstly, remove their related user group user.groups.remove(instance.group) + with suppress(SocialAccount.DoesNotExist, DiscordUser.DoesNotExist): + # If we get either exception, then the user could not have been assigned staff + # with our system in the first place. + + social_account = SocialAccount.objects.get(user=user, provider=DiscordProvider.id) + discord_user = DiscordUser.objects.get(id=int(social_account.uid)) + + mappings = RoleMapping.objects.filter(role__id__in=discord_user.roles).all() + is_staff = any(m.is_staff for m in mappings) + + if user.is_staff != is_staff: + user.is_staff = is_staff + user.save(update_fields=("is_staff", )) + def mapping_model_updated(self, sender: Type[RoleMapping], **kwargs) -> None: """ Processes update signals from the RoleMapping model. @@ -168,12 +185,27 @@ class AllauthSignalListener: self.mapping_model_deleted(RoleMapping, instance=old_instance) accounts = SocialAccount.objects.filter( - uid__in=(u.id for u in instance.role.user_set.all()) + uid__in=(u.id for u in DiscordUser.objects.filter(roles__contains=[instance.role.id])) ) for account in accounts: account.user.groups.add(instance.group) + if instance.is_staff and not account.user.is_staff: + account.user.is_staff = instance.is_staff + account.user.save(update_fields=("is_staff", )) + else: + discord_user = DiscordUser.objects.get(id=int(account.uid)) + + mappings = RoleMapping.objects.filter( + role__id__in=discord_user.roles + ).exclude(id=instance.id).all() + is_staff = any(m.is_staff for m in mappings) + + if account.user.is_staff != is_staff: + account.user.is_staff = is_staff + account.user.save(update_fields=("is_staff",)) + def user_model_updated(self, sender: Type[DiscordUser], **kwargs) -> None: """ Processes update signals from the Discord User model, assigning perms as required. @@ -230,31 +262,53 @@ class AllauthSignalListener: except SocialAccount.user.RelatedObjectDoesNotExist: return # There's no user account yet, this will be handled by another receiver + # Ensure that the username on this account is correct + new_username = f"{user.name}#{user.discriminator}" + + if account.user.username != new_username: + account.user.username = new_username + account.user.first_name = new_username + if not user.in_guild: deletion = True if deletion: # They've unlinked Discord or left the server, so we have to remove their groups + # and their staff status - if not current_groups: - return # They have no groups anyway, no point in processing + if current_groups: + # They do have groups, so let's remove them + account.user.groups.remove( + *(mapping.group for mapping in mappings) + ) - account.user.groups.remove( - *(mapping.group for mapping in mappings) - ) + if account.user.is_staff: + # They're marked as a staff user and they shouldn't be, so let's fix that + account.user.is_staff = False else: new_groups = [] + is_staff = False - for role in user.roles.all(): + for role in user.roles: try: - new_groups.append(mappings.get(role=role).group) + mapping = mappings.get(role__id=role) except RoleMapping.DoesNotExist: continue # No mapping exists - account.user.groups.add( - *[group for group in new_groups if group not in current_groups] - ) + new_groups.append(mapping.group) - account.user.groups.remove( - *[mapping.group for mapping in mappings if mapping.group not in new_groups] - ) + if mapping.is_staff: + is_staff = True + + account.user.groups.add( + *[group for group in new_groups if group not in current_groups] + ) + + account.user.groups.remove( + *[mapping.group for mapping in mappings if mapping.group not in new_groups] + ) + + if account.user.is_staff != is_staff: + account.user.is_staff = is_staff + + account.user.save() |