From 156ad09232ffc54b4d62b7b36b45c5cd1b7b66f3 Mon Sep 17 00:00:00 2001 From: poduck Date: Mon, 8 Dec 2025 10:11:38 -0500 Subject: [PATCH] fix: Use request.tenant instead of request.user.tenant for user validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform-level users (owners) may have tenant=None on their user record but still access tenant subdomains. The _get_valid_user method now uses request.tenant (from django-tenants middleware) which is set based on the subdomain being accessed, not the user's tenant FK. This fixes 400 Bad Request errors when platform users try to create resources with staff assignments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../scheduling/schedule/serializers.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/smoothschedule/smoothschedule/scheduling/schedule/serializers.py b/smoothschedule/smoothschedule/scheduling/schedule/serializers.py index 9caef61..a9b0248 100644 --- a/smoothschedule/smoothschedule/scheduling/schedule/serializers.py +++ b/smoothschedule/smoothschedule/scheduling/schedule/serializers.py @@ -223,10 +223,14 @@ class ResourceSerializer(serializers.ModelSerializer): def _get_valid_user(self, user_id): """ - Get a user by ID, validating they belong to the same tenant as the request user. + Get a user by ID, validating they belong to the same tenant as the request. Returns None if user doesn't exist or doesn't belong to the same tenant. CRITICAL: This prevents cross-tenant user linking (multi-tenancy security). + + Uses request.tenant (from django-tenants middleware) rather than request.user.tenant + because platform-level users (owners) may have tenant=None on their user record + but still access tenant subdomains. """ if not user_id: return None @@ -235,10 +239,16 @@ class ResourceSerializer(serializers.ModelSerializer): if not request or not request.user.is_authenticated: return None + # Use request.tenant (from django-tenants middleware) - this is set based on + # the subdomain being accessed, not the user's tenant FK + tenant = getattr(request, 'tenant', None) + if not tenant: + return None + try: user = User.objects.get(id=user_id) - # Verify user belongs to the same tenant - if request.user.tenant and user.tenant == request.user.tenant: + # Verify user belongs to the same tenant as the request + if user.tenant == tenant: return user return None except User.DoesNotExist: