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 from .models import User, UserProfile, EmailVerification from security import safe_requests @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): """Create UserProfile for new users""" try: if created: # Create profile profile = UserProfile.objects.create(user=instance) # If user has a social account with avatar, download it 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: try: response = safe_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(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): """Ensure UserProfile exists and is saved""" try: if not hasattr(instance, 'profile'): UserProfile.objects.create(user=instance) instance.profile.save() except Exception as e: print(f"Error saving 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.Roles.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.Roles.USER: new_group, _ = Group.objects.get_or_create(name=instance.role) instance.groups.add(new_group) # Special handling for superuser role if instance.role == User.Roles.SUPERUSER: instance.is_superuser = True instance.is_staff = True elif old_instance.role == User.Roles.SUPERUSER: # If removing superuser role, remove superuser status instance.is_superuser = False if instance.role not in [User.Roles.ADMIN, User.Roles.MODERATOR]: instance.is_staff = False # Handle staff status for admin and moderator roles if instance.role in [User.Roles.ADMIN, User.Roles.MODERATOR]: instance.is_staff = True elif old_instance.role in [User.Roles.ADMIN, User.Roles.MODERATOR]: # If removing admin/moderator role, remove staff status if instance.role not in [User.Roles.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 from django.contrib.contenttypes.models import ContentType # Create Moderator group moderator_group, _ = Group.objects.get_or_create(name=User.Roles.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=User.Roles.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)}")