mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-11 05:20:16 +02:00
Hopefully this will fix the infinite recursion. Elevate logging messages to Info so they appear in logs with the default configuration.
156 lines
7.6 KiB
Python
156 lines
7.6 KiB
Python
import logging
|
|
|
|
from .models import CharacterOwnership, UserProfile, get_guest_state, State
|
|
from django.contrib.auth.models import User
|
|
from django.db.models import Q
|
|
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete, m2m_changed
|
|
from django.dispatch import receiver, Signal
|
|
from esi.models import Token
|
|
|
|
from allianceauth.eveonline.models import EveCharacter
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
state_changed = Signal(providing_args=['user', 'state'])
|
|
|
|
|
|
def trigger_state_check(state):
|
|
# evaluate all current members to ensure they still have access
|
|
for profile in state.userprofile_set.all():
|
|
profile.assign_state()
|
|
|
|
# we may now be available to others with lower states
|
|
check_states = State.objects.filter(priority__lt=state.priority)
|
|
for profile in UserProfile.objects.filter(state__in=check_states):
|
|
if state.available_to_user(profile.user):
|
|
profile.state = state
|
|
profile.save(update_fields=['state'])
|
|
state_changed.send(sender=state.__class__, user=profile.user, state=state)
|
|
|
|
|
|
@receiver(m2m_changed, sender=State.member_characters.through)
|
|
def state_member_characters_changed(sender, instance, action, *args, **kwargs):
|
|
if action.startswith('post_'):
|
|
logger.debug('State {} member characters changed. Re-evaluating membership.'.format(instance))
|
|
trigger_state_check(instance)
|
|
|
|
|
|
@receiver(m2m_changed, sender=State.member_corporations.through)
|
|
def state_member_corporations_changed(sender, instance, action, *args, **kwargs):
|
|
if action.startswith('post_'):
|
|
logger.debug('State {} member corporations changed. Re-evaluating membership.'.format(instance))
|
|
trigger_state_check(instance)
|
|
|
|
|
|
@receiver(m2m_changed, sender=State.member_alliances.through)
|
|
def state_member_alliances_changed(sender, instance, action, *args, **kwargs):
|
|
if action.startswith('post_'):
|
|
logger.debug('State {} member alliances changed. Re-evaluating membership.'.format(instance))
|
|
trigger_state_check(instance)
|
|
|
|
|
|
@receiver(post_save, sender=State)
|
|
def state_saved(sender, instance, *args, **kwargs):
|
|
logger.debug('State {} saved. Re-evaluating membership.'.format(instance))
|
|
trigger_state_check(instance)
|
|
|
|
|
|
# Is there a smarter way to intercept pre_save with a diff main_character or state?
|
|
@receiver(post_save, sender=UserProfile)
|
|
def reassess_on_profile_save(sender, instance, created, *args, **kwargs):
|
|
# catches post_save from profiles to trigger necessary service and state checks
|
|
if not created:
|
|
update_fields = kwargs.pop('update_fields', []) or []
|
|
if 'state' not in update_fields:
|
|
logger.debug('Profile for {} saved without state change. Re-evaluating state.'.format(instance.user))
|
|
instance.assign_state()
|
|
|
|
|
|
@receiver(post_save, sender=User)
|
|
def create_required_models(sender, instance, created, *args, **kwargs):
|
|
# ensure all users have a model
|
|
if created:
|
|
logger.debug('User {} created. Creating default UserProfile.'.format(instance))
|
|
UserProfile.objects.get_or_create(user=instance)
|
|
|
|
|
|
@receiver(post_save, sender=Token)
|
|
def record_character_ownership(sender, instance, created, *args, **kwargs):
|
|
if created:
|
|
logger.debug('New token for {0} character {1} saved. Evaluating ownership.'.format(instance.user,
|
|
instance.character_name))
|
|
if instance.user:
|
|
query = Q(owner_hash=instance.character_owner_hash) & Q(user=instance.user)
|
|
else:
|
|
query = Q(owner_hash=instance.character_owner_hash)
|
|
# purge ownership records if the hash or auth user account has changed
|
|
CharacterOwnership.objects.filter(character__character_id=instance.character_id).exclude(query).delete()
|
|
# create character if needed
|
|
if EveCharacter.objects.filter(character_id=instance.character_id).exists() is False:
|
|
logger.debug('Token is for a new character. Creating model for {0} ({1})'.format(instance.character_name,
|
|
instance.character_id))
|
|
EveCharacter.objects.create_character(instance.character_id)
|
|
char = EveCharacter.objects.get(character_id=instance.character_id)
|
|
# check if we need to create ownership
|
|
if instance.user and not CharacterOwnership.objects.filter(
|
|
character__character_id=instance.character_id).exists():
|
|
logger.debug("Character {0} is not yet owned. Assigning ownership to {1}".format(instance.character_name,
|
|
instance.user))
|
|
CharacterOwnership.objects.update_or_create(character=char,
|
|
defaults={'owner_hash': instance.character_owner_hash,
|
|
'user': instance.user})
|
|
|
|
|
|
@receiver(pre_delete, sender=CharacterOwnership)
|
|
def validate_main_character(sender, instance, *args, **kwargs):
|
|
if instance.user.profile.main_character == instance.character:
|
|
logger.info("Ownership of a main character {0} has been revoked. Resetting {1} main character.".format(
|
|
instance.character, instance.user))
|
|
# clear main character as user no longer owns them
|
|
instance.user.profile.main_character = None
|
|
instance.user.profile.save()
|
|
|
|
|
|
@receiver(post_delete, sender=Token)
|
|
def validate_main_character_token(sender, instance, *args, **kwargs):
|
|
if UserProfile.objects.filter(main_character__character_id=instance.character_id).exists():
|
|
logger.debug(
|
|
"Token for a main character {0} is being deleted. Ensuring there are valid tokens to refresh.".format(
|
|
instance.character_name))
|
|
profile = UserProfile.objects.get(main_character__character_id=instance.character_id)
|
|
if not Token.objects.filter(character_id=instance.character_id).filter(
|
|
user=profile.user).require_valid().exists():
|
|
logger.info(
|
|
"No remaining tokens to validate {0} ownership of main character {1}. Resetting main character.".format(
|
|
profile.user, profile.main_character))
|
|
# clear main character as we can no longer verify ownership
|
|
profile.main_character = None
|
|
profile.save()
|
|
|
|
|
|
@receiver(pre_save, sender=User)
|
|
def assign_state_on_active_change(sender, instance, *args, **kwargs):
|
|
# set to guest state if inactive, assign proper state if reactivated
|
|
if instance.pk:
|
|
old_instance = User.objects.get(pk=instance.pk)
|
|
if old_instance.is_active != instance.is_active:
|
|
if instance.is_active:
|
|
logger.debug("User {0} has been activated. Assigning state.".format(instance))
|
|
instance.profile.assign_state()
|
|
else:
|
|
logger.debug(
|
|
"User {0} has been deactivated. Revoking state and assigning to guest state.".format(instance))
|
|
instance.profile.state = get_guest_state()
|
|
instance.profile.save(update_fields=['state'])
|
|
|
|
|
|
@receiver(post_save, sender=EveCharacter)
|
|
def check_state_on_character_update(sender, instance, *args, **kwargs):
|
|
# if this is a main character updating, check that user's state
|
|
try:
|
|
logger.debug("Character {0} has been saved. Assessing owner's state for changes.".format(instance))
|
|
instance.userprofile.assign_state()
|
|
except UserProfile.DoesNotExist:
|
|
logger.debug("Character {0} is not a main character. No state assessment required.".format(instance))
|
|
pass
|