Files
dealerhub/backend/apps/core/permissions.py
T

47 lines
1.6 KiB
Python

"""租户授权权限类。
X-Tenant-Id 只选择请求上下文;已认证用户必须拥有该租户的有效 membership。
公开端点显式使用 AllowAny,因此不会被此默认权限类改变。
"""
from django.conf import settings
from rest_framework.permissions import BasePermission
class TenantMembershipPermission(BasePermission):
"""Require an active user membership for the requested tenant."""
message = "当前用户无权访问该租户"
code = "tenant_membership_required"
def has_permission(self, request, view):
user = getattr(request, "user", None)
if not user or not user.is_authenticated:
return False
# API keys are already cryptographically bound to their tenant. Keep
# their existing header-optional contract, but reject an explicit
# attempt to select a different tenant.
auth = getattr(request, "auth", None)
if auth is not None and auth.__class__.__name__ == "APIKey":
key_tenant = getattr(auth, "tenant", None)
requested = request.META.get("HTTP_X_TENANT_ID")
return key_tenant is not None and (
not requested or requested == key_tenant.code
)
tenant_code = request.META.get(
"HTTP_X_TENANT_ID", getattr(settings, "TENANT_DEFAULT", "default")
)
if not tenant_code:
return False
from .models import Tenant, TenantMembership
return TenantMembership.objects.filter(
user=user,
tenant__code=tenant_code,
tenant__is_active=True,
is_active=True,
).exists()