import django.core.exceptions from rest_framework import viewsets from rest_framework.exceptions import ValidationError from rest_framework.permissions import IsAuthenticated, SAFE_METHODS from rest_framework.response import Response from rest_framework.reverse import reverse from rest_framework.views import APIView from desecapi import permissions from desecapi.models import TokenDomainPolicy from desecapi.serializers import TokenDomainPolicySerializer, TokenSerializer from .base import IdempotentDestroyMixin from .domains import DomainViewSet class TokenViewSet(IdempotentDestroyMixin, viewsets.ModelViewSet): serializer_class = TokenSerializer permission_classes = ( IsAuthenticated, permissions.HasManageTokensPermission, ) throttle_scope = "account_management_passive" def get_queryset(self): return self.request.user.token_set.all() def get_serializer(self, *args, **kwargs): # When creating a new token, return the plaintext representation if self.action == "create": kwargs.setdefault("include_plain", True) return super().get_serializer(*args, **kwargs) def perform_create(self, serializer): serializer.save(user=self.request.user) class TokenPoliciesRoot(APIView): permission_classes = [ IsAuthenticated, permissions.HasManageTokensPermission | permissions.AuthTokenCorrespondsToViewToken, ] def get(self, request, *args, **kwargs): return Response( { "domain": reverse( "token_domain_policies-list", request=request, kwargs=kwargs ) } ) class TokenDomainPolicyViewSet(IdempotentDestroyMixin, viewsets.ModelViewSet): lookup_field = "domain__name" lookup_value_regex = DomainViewSet.lookup_value_regex pagination_class = None serializer_class = TokenDomainPolicySerializer throttle_scope = "account_management_passive" @property def permission_classes(self): ret = [IsAuthenticated] if self.request.method in SAFE_METHODS: ret.append( permissions.HasManageTokensPermission | permissions.AuthTokenCorrespondsToViewToken ) else: ret.append(permissions.HasManageTokensPermission) return ret def dispatch(self, request, *args, **kwargs): # map default policy onto domain_id IS NULL lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field try: if kwargs[lookup_url_kwarg] == "default": kwargs[lookup_url_kwarg] = None except KeyError: pass return super().dispatch(request, *args, **kwargs) def get_queryset(self): return TokenDomainPolicy.objects.filter( token_id=self.kwargs["token_id"], token__user=self.request.user ) def perform_destroy(self, instance): try: super().perform_destroy(instance) except django.core.exceptions.ValidationError as exc: raise ValidationError(exc.message_dict, code="precedence")