✨(backend) add ServiceProvider
This adds the ServiceProvider notion to allow to better manage which teams is available for each service provider.
This commit is contained in:
@@ -4,6 +4,7 @@ from rest_framework import exceptions, serializers
|
||||
from timezone_field.rest_framework import TimeZoneSerializerField
|
||||
|
||||
from core import models
|
||||
from core.models import ServiceProvider
|
||||
|
||||
|
||||
class ContactSerializer(serializers.ModelSerializer):
|
||||
@@ -205,6 +206,9 @@ class TeamSerializer(serializers.ModelSerializer):
|
||||
"""Serialize teams."""
|
||||
|
||||
abilities = serializers.SerializerMethodField(read_only=True)
|
||||
service_providers = serializers.PrimaryKeyRelatedField(
|
||||
queryset=ServiceProvider.objects.all(), many=True, required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = models.Team
|
||||
@@ -215,6 +219,7 @@ class TeamSerializer(serializers.ModelSerializer):
|
||||
"abilities",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"service_providers",
|
||||
]
|
||||
read_only_fields = [
|
||||
"id",
|
||||
@@ -226,6 +231,13 @@ class TeamSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Create a new team with organization enforcement."""
|
||||
# When called as a resource server, we enforce the team service provider
|
||||
if sp_audience := self.context.get("from_service_provider_audience", None):
|
||||
service_provider, _created = models.ServiceProvider.objects.get_or_create(
|
||||
audience_id=sp_audience
|
||||
)
|
||||
validated_data["service_providers"] = [service_provider]
|
||||
|
||||
# Note: this is not the purpose of this API to check the user has an organization
|
||||
return super().create(
|
||||
validated_data=validated_data
|
||||
|
||||
@@ -18,6 +18,7 @@ from rest_framework.permissions import AllowAny
|
||||
|
||||
from core import models
|
||||
|
||||
from ..resource_server.authentication import ResourceServerAuthentication
|
||||
from . import permissions, serializers
|
||||
|
||||
SIMILARITY_THRESHOLD = 0.04
|
||||
@@ -247,15 +248,52 @@ class TeamViewSet(
|
||||
queryset = models.Team.objects.all()
|
||||
pagination_class = None
|
||||
|
||||
def _get_service_provider_audience(self):
|
||||
"""Return the audience of the Service Provider from the OIDC introspected token."""
|
||||
if not isinstance(
|
||||
self.request.successful_authenticator, ResourceServerAuthentication
|
||||
):
|
||||
# We could check request.resource_server_token_audience here, but it's
|
||||
# more explicit to check the authenticator type and assert the attribute
|
||||
# existence.
|
||||
return None
|
||||
|
||||
# When used as a resource server, the request has a token audience
|
||||
service_provider_audience = self.request.resource_server_token_audience
|
||||
|
||||
if not service_provider_audience: # should not happen
|
||||
raise exceptions.AuthenticationFailed(
|
||||
"Resource server token audience not found in request"
|
||||
)
|
||||
|
||||
return service_provider_audience
|
||||
|
||||
def get_queryset(self):
|
||||
"""Custom queryset to get user related teams."""
|
||||
user_role_query = models.TeamAccess.objects.filter(
|
||||
user=self.request.user, team=OuterRef("pk")
|
||||
).values("role")[:1]
|
||||
return models.Team.objects.filter(accesses__user=self.request.user).annotate(
|
||||
user_role=Subquery(user_role_query)
|
||||
|
||||
return (
|
||||
models.Team.objects.prefetch_related("accesses", "service_providers")
|
||||
.filter(
|
||||
accesses__user=self.request.user,
|
||||
)
|
||||
.annotate(user_role=Subquery(user_role_query))
|
||||
)
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""Extra context provided to the serializer class."""
|
||||
context = super().get_serializer_context()
|
||||
|
||||
# When used as a resource server, we need to know the audience to automatically:
|
||||
# - add the Service Provider to the team "scope" on creation
|
||||
context["from_service_provider_audience"] = (
|
||||
self._get_service_provider_audience()
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
def perform_create(self, serializer):
|
||||
"""Set the current user as owner of the newly created team."""
|
||||
team = serializer.save()
|
||||
|
||||
Reference in New Issue
Block a user