fix: Use request.tenant for staff filtering in multi-tenant context
- UserTenantFilteredMixin now uses request.tenant (from django-tenants middleware) instead of request.user.tenant for filtering - ResourceSerializer._get_valid_user uses request.tenant for validation - Frontend useResources sends user_id instead of user field This fixes 400 errors when creating staff resources because the tenant context is now correctly derived from the subdomain being accessed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -70,8 +70,7 @@ export const useCreateResource = () => {
|
||||
const backendData: any = {
|
||||
name: resourceData.name,
|
||||
type: resourceData.type,
|
||||
user: resourceData.userId ? parseInt(resourceData.userId) : null,
|
||||
timezone: 'UTC', // Default timezone
|
||||
user_id: resourceData.userId ? parseInt(resourceData.userId) : null,
|
||||
};
|
||||
|
||||
if (resourceData.maxConcurrentEvents !== undefined) {
|
||||
|
||||
@@ -310,14 +310,21 @@ class UserTenantFilteredMixin(SandboxFilteredQuerySetMixin):
|
||||
"""
|
||||
|
||||
def filter_queryset_for_tenant(self, queryset):
|
||||
"""Filter users by tenant foreign key."""
|
||||
"""Filter users by tenant foreign key.
|
||||
|
||||
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.
|
||||
"""
|
||||
queryset = super().filter_queryset_for_tenant(queryset)
|
||||
|
||||
user = self.request.user
|
||||
if user.tenant:
|
||||
queryset = queryset.filter(tenant=user.tenant)
|
||||
# Use request.tenant (from middleware) - this is set based on the
|
||||
# subdomain being accessed, not the user's tenant FK
|
||||
request_tenant = getattr(self.request, 'tenant', None)
|
||||
if request_tenant:
|
||||
queryset = queryset.filter(tenant=request_tenant)
|
||||
else:
|
||||
# User has no tenant - return empty for safety
|
||||
# No tenant on request - return empty for safety
|
||||
return queryset.none()
|
||||
|
||||
return queryset
|
||||
|
||||
@@ -232,26 +232,42 @@ class ResourceSerializer(serializers.ModelSerializer):
|
||||
because platform-level users (owners) may have tenant=None on their user record
|
||||
but still access tenant subdomains.
|
||||
"""
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.warning(f"_get_valid_user called with user_id={user_id}")
|
||||
|
||||
if not user_id:
|
||||
logger.warning("_get_valid_user: user_id is empty, returning None")
|
||||
return None
|
||||
|
||||
request = self.context.get('request')
|
||||
if not request or not request.user.is_authenticated:
|
||||
logger.warning(f"_get_valid_user: no request or not authenticated, returning None")
|
||||
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)
|
||||
logger.warning(f"_get_valid_user: request.tenant={tenant}, request.user={request.user}, request.user.tenant={getattr(request.user, 'tenant', 'N/A')}")
|
||||
|
||||
if not tenant:
|
||||
logger.warning("_get_valid_user: no tenant on request, returning None")
|
||||
return None
|
||||
|
||||
try:
|
||||
user = User.objects.get(id=user_id)
|
||||
logger.warning(f"_get_valid_user: found user {user.email}, user.tenant={user.tenant}, comparing to request.tenant={tenant}")
|
||||
|
||||
# Verify user belongs to the same tenant as the request
|
||||
if user.tenant == tenant:
|
||||
logger.warning(f"_get_valid_user: tenant match! Returning user")
|
||||
return user
|
||||
|
||||
logger.warning(f"_get_valid_user: tenant mismatch, returning None")
|
||||
return None
|
||||
except User.DoesNotExist:
|
||||
logger.warning(f"_get_valid_user: user {user_id} not found")
|
||||
return None
|
||||
|
||||
def _is_staff_type(self, resource_type=None, legacy_type=None):
|
||||
@@ -274,6 +290,10 @@ class ResourceSerializer(serializers.ModelSerializer):
|
||||
Validate that staff-type resources have a user assigned.
|
||||
Staff resources MUST be linked to a staff member.
|
||||
"""
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.warning(f"ResourceSerializer.validate called with attrs={attrs}")
|
||||
|
||||
user_id = attrs.get('user_id')
|
||||
resource_type = attrs.get('resource_type')
|
||||
legacy_type = attrs.get('type')
|
||||
|
||||
Reference in New Issue
Block a user