from rest_framework import serializers from .models import Hub, HubPermission, Tags # Maps Hub fields -> the HubPermission flag that allows changing them FIELD_PERMISSION_MAP = { 'name': 'changing_name', 'description': 'changing_description', 'icon': 'changing_icon', 'banner': 'changing_banner', 'members': 'managing_members', } class TransferInitSerializer(serializers.Serializer): user_id = serializers.IntegerField(help_text="PK of the user to transfer ownership to.") class TransferVerifySerializer(serializers.Serializer): token = serializers.UUIDField(help_text="Transfer token sent to the new owner.") class TagsSerializer(serializers.ModelSerializer): class Meta: model = Tags fields = ['id', 'name', 'description', 'color'] class HubPermissionSerializer(serializers.ModelSerializer): class Meta: model = HubPermission fields = [ 'id', 'user', 'changing_name', 'changing_description', 'changing_icon', 'changing_banner', 'managing_members', 'managing_posts', 'managing_chats', ] class HubSerializer(serializers.ModelSerializer): tags = TagsSerializer(many=True, read_only=True) moderators = HubPermissionSerializer(many=True, read_only=True) class Meta: model = Hub fields = [ 'id', 'name', 'description', 'owner', 'icon', 'banner', 'members', 'is_public', 'tags', 'moderators', ] read_only_fields = ['owner'] def validate(self, attrs): hub = self.instance # None on create — no restrictions needed if hub is None: return attrs request = self.context.get('request') if request is None: return attrs user = request.user # Owner and superuser bypass field-level checks if hub.owner == user or user.is_superuser: return attrs # Moderator: enforce per-field permission flags try: perm = hub.moderators.get(user=user) except HubPermission.DoesNotExist: raise serializers.ValidationError('You do not have permission to edit this hub.') for field in attrs: flag = FIELD_PERMISSION_MAP.get(field) if flag and not getattr(perm, flag, False): raise serializers.ValidationError( {field: 'You do not have permission to change this field.'} ) return attrs