Răsfoiți Sursa

adds additional parameters for token provision api #12870

Abhimanyu Saharan 2 ani în urmă
părinte
comite
7848beedce
2 a modificat fișierele cu 50 adăugiri și 28 ștergeri
  1. 38 4
      netbox/users/api/serializers.py
  2. 12 24
      netbox/users/api/views.py

+ 38 - 4
netbox/users/api/serializers.py

@@ -1,11 +1,12 @@
 from django.conf import settings
+from django.contrib.auth import authenticate
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Group
 from django.contrib.contenttypes.models import ContentType
 from drf_spectacular.utils import extend_schema_field
 from drf_spectacular.types import OpenApiTypes
 from rest_framework import serializers
-from rest_framework.exceptions import PermissionDenied
+from rest_framework.exceptions import AuthenticationFailed, PermissionDenied
 
 from netbox.api.fields import ContentTypeField, IPNetworkSerializer, SerializedPKRelatedField
 from netbox.api.serializers import ValidatedModelSerializer
@@ -107,9 +108,42 @@ class TokenSerializer(ValidatedModelSerializer):
         return super().validate(data)
 
 
-class TokenProvisionSerializer(serializers.Serializer):
-    username = serializers.CharField()
-    password = serializers.CharField()
+class TokenProvisionSerializer(TokenSerializer):
+    user = NestedUserSerializer(
+        read_only=True
+    )
+    username = serializers.CharField(
+        write_only=True
+    )
+    password = serializers.CharField(
+        write_only=True
+    )
+    last_used = serializers.DateTimeField(
+        read_only=True
+    )
+    key = serializers.CharField(
+        read_only=True
+    )
+
+    class Meta:
+        model = Token
+        fields = (
+            'id', 'url', 'display', 'user', 'created', 'expires', 'last_used', 'key', 'write_enabled', 'description',
+            'allowed_ips', 'username', 'password',
+        )
+
+    def validate(self, data):
+        # Validate the username and password
+        username = data.pop('username')
+        password = data.pop('password')
+        user = authenticate(request=self.context.get('request'), username=username, password=password)
+        if user is None:
+            raise AuthenticationFailed("Invalid username/password")
+
+        # Inject the user into the validated data
+        data['user'] = user
+
+        return data
 
 
 class ObjectPermissionSerializer(ValidatedModelSerializer):

+ 12 - 24
netbox/users/api/views.py

@@ -1,3 +1,4 @@
+import logging
 from django.contrib.auth import authenticate
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Group
@@ -63,34 +64,21 @@ class TokenProvisionView(APIView):
     @extend_schema(
         request=serializers.TokenProvisionSerializer,
         responses={
-            201: serializers.TokenSerializer,
+            201: serializers.TokenProvisionSerializer,
             401: OpenApiTypes.OBJECT,
         }
     )
     def post(self, request):
-        serializer = serializers.TokenProvisionSerializer(data=request.data)
-        serializer.is_valid()
-
-        # Authenticate the user account based on the provided credentials
-        username = serializer.data.get('username')
-        password = serializer.data.get('password')
-        if not username or not password:
-            raise AuthenticationFailed("Username and password must be provided to provision a token.")
-        user = authenticate(request=request, username=username, password=password)
-        if user is None:
-            raise AuthenticationFailed("Invalid username/password")
-
-        # Create a new Token for the User
-        token = Token(user=user)
-        token.save()
-        data = serializers.TokenSerializer(token, context={'request': request}).data
-        # Manually append the token key, which is normally write-only
-        data['key'] = token.key
-
-        return Response(data, status=HTTP_201_CREATED)
-
-    def get_serializer_class(self):
-        return serializers.TokenSerializer
+        serializer = serializers.TokenProvisionSerializer(data=request.data, context={'request': request})
+        serializer.is_valid(raise_exception=True)
+        self.perform_create(serializer)
+        return Response(serializer.data, status=HTTP_201_CREATED)
+
+    def perform_create(self, serializer):
+        model = serializer.Meta.model
+        logger = logging.getLogger(f'netbox.api.views.TokenProvisionView')
+        logger.info(f"Creating new {model._meta.verbose_name}")
+        serializer.save()
 
 
 #