Files
thrillwiki_django_no_react/accounts/signals.py
2025-07-16 03:18:05 +00:00

153 lines
6.9 KiB
Python

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)}")