Files
thrillwiki_django_no_react/accounts/signals.py
pacnpal 66ed4347a9 Refactor test utilities and enhance ASGI settings
- Cleaned up and standardized assertions in ApiTestMixin for API response validation.
- Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE.
- Removed unused imports and improved formatting in settings.py.
- Refactored URL patterns in urls.py for better readability and organization.
- Enhanced view functions in views.py for consistency and clarity.
- Added .flake8 configuration for linting and style enforcement.
- Introduced type stubs for django-environ to improve type checking with Pylance.
2025-08-20 19:51:59 -04:00

190 lines
7.3 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
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"""
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 = 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:
# Try to get existing profile first
try:
profile = instance.profile
profile.save()
except UserProfile.DoesNotExist:
# Profile doesn't exist, create it
UserProfile.objects.create(user=instance)
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
# 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)}")