from django.db.models.signals import post_save, pre_save from django.dispatch import receiver from django.contrib.auth.models import Group from django.db import transaction from django.core.files import File from django.core.files.temp import NamedTemporaryFile import requests from .models import User, UserProfile @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): """Create UserProfile for new users - unified signal handler""" if created: try: # Use get_or_create to prevent duplicates profile, profile_created = UserProfile.objects.get_or_create(user=instance) if profile_created: # If user has a social account with avatar, download it try: social_account = instance.socialaccount_set.first() if social_account: extra_data = social_account.extra_data avatar_url = None if social_account.provider == "google": avatar_url = extra_data.get("picture") elif social_account.provider == "discord": avatar = extra_data.get("avatar") discord_id = extra_data.get("id") if avatar: avatar_url = f"https://cdn.discordapp.com/avatars/{discord_id}/{avatar}.png" if avatar_url: response = requests.get(avatar_url, timeout=60) if response.status_code == 200: img_temp = NamedTemporaryFile(delete=True) img_temp.write(response.content) img_temp.flush() file_name = f"avatar_{instance.username}.png" profile.avatar.save(file_name, File(img_temp), save=True) except Exception as e: print(f"Error downloading avatar for user {instance.username}: {str(e)}") except Exception as e: print(f"Error creating profile for user {instance.username}: {str(e)}") @receiver(pre_save, sender=User) def sync_user_role_with_groups(sender, instance, **kwargs): """Sync user role with Django groups""" if instance.pk: # Only for existing users try: old_instance = User.objects.get(pk=instance.pk) if old_instance.role != instance.role: # Role has changed, update groups with transaction.atomic(): # Remove from old role group if exists if old_instance.role != "USER": old_group = Group.objects.filter(name=old_instance.role).first() if old_group: instance.groups.remove(old_group) # Add to new role group if instance.role != "USER": new_group, _ = Group.objects.get_or_create(name=instance.role) instance.groups.add(new_group) # Special handling for superuser role if instance.role == "SUPERUSER": instance.is_superuser = True instance.is_staff = True elif old_instance.role == "SUPERUSER": # If removing superuser role, remove superuser # status instance.is_superuser = False if instance.role not in [ "ADMIN", "MODERATOR", ]: instance.is_staff = False # Handle staff status for admin and moderator roles if instance.role in [ "ADMIN", "MODERATOR", ]: instance.is_staff = True elif old_instance.role in [ "ADMIN", "MODERATOR", ]: # If removing admin/moderator role, remove staff # status if instance.role not in ["SUPERUSER"]: instance.is_staff = False except User.DoesNotExist: pass except Exception as e: print( f"Error syncing role with groups for user {instance.username}: {str(e)}" ) def create_default_groups(): """ Create default groups with appropriate permissions. Call this in a migration or management command. """ try: from django.contrib.auth.models import Permission # Create Moderator group moderator_group, _ = Group.objects.get_or_create(name="MODERATOR") moderator_permissions = [ # Review moderation permissions "change_review", "delete_review", "change_reviewreport", "delete_reviewreport", # Edit moderation permissions "change_parkedit", "delete_parkedit", "change_rideedit", "delete_rideedit", "change_companyedit", "delete_companyedit", "change_manufactureredit", "delete_manufactureredit", ] # Create Admin group admin_group, _ = Group.objects.get_or_create(name="ADMIN") admin_permissions = moderator_permissions + [ # User management permissions "change_user", "delete_user", # Content management permissions "add_park", "change_park", "delete_park", "add_ride", "change_ride", "delete_ride", "add_company", "change_company", "delete_company", "add_manufacturer", "change_manufacturer", "delete_manufacturer", ] # Assign permissions to groups for codename in moderator_permissions: try: perm = Permission.objects.get(codename=codename) moderator_group.permissions.add(perm) except Permission.DoesNotExist: print(f"Permission not found: {codename}") for codename in admin_permissions: try: perm = Permission.objects.get(codename=codename) admin_group.permissions.add(perm) except Permission.DoesNotExist: print(f"Permission not found: {codename}") except Exception as e: print(f"Error creating default groups: {str(e)}")