Просмотр исходного кода

Fixes #20476: Prohibit changing a token's owner (#20576)

Jeremy Stretch 4 месяцев назад
Родитель
Сommit
b7cc4c418b

+ 9 - 0
netbox/users/api/serializers_/tokens.py

@@ -37,6 +37,15 @@ class TokenSerializer(ValidatedModelSerializer):
         read_only_fields = ('key',)
         brief_fields = ('id', 'url', 'display', 'version', 'key', 'write_enabled', 'description')
 
+    def get_fields(self):
+        fields = super().get_fields()
+
+        # Make user field read-only if updating an existing Token.
+        if self.instance is not None:
+            fields['user'].read_only = True
+
+        return fields
+
     def validate(self, data):
 
         # If the Token is being created on behalf of another user, enforce the grant_token permission.

+ 7 - 0
netbox/users/forms/model_forms.py

@@ -177,6 +177,13 @@ class TokenForm(UserTokenForm):
             'version', 'token', 'user', 'write_enabled', 'expires', 'description', 'allowed_ips',
         ]
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        # If not creating a new Token, disable the user field
+        if self.instance and not self.instance._state.adding:
+            self.fields['user'].disabled = True
+
 
 class UserForm(forms.ModelForm):
     password = forms.CharField(

+ 26 - 3
netbox/users/tests/test_api.py

@@ -212,9 +212,9 @@ class TokenTest(
     @classmethod
     def setUpTestData(cls):
         users = (
-            create_test_user('User1'),
-            create_test_user('User2'),
-            create_test_user('User3'),
+            create_test_user('User 1'),
+            create_test_user('User 2'),
+            create_test_user('User 3'),
         )
 
         tokens = (
@@ -238,6 +238,10 @@ class TokenTest(
             },
         ]
 
+        cls.update_data = {
+            'description': 'Token 1',
+        }
+
     def test_provision_token_valid(self):
         """
         Test the provisioning of a new REST API token given a valid username and password.
@@ -300,6 +304,25 @@ class TokenTest(
         response = self.client.post(url, data, format='json', **self.header)
         self.assertEqual(response.status_code, 201)
 
+    def test_reassign_token(self):
+        """
+        Check that a Token cannot be reassigned to another User.
+        """
+        user1 = User.objects.get(username='User 1')
+        user2 = User.objects.get(username='User 2')
+        token1 = Token.objects.filter(user=user1).first()
+        self.add_permissions('users.change_token')
+
+        data = {
+            'user': user2.pk,
+        }
+        url = self._get_detail_url(token1)
+        response = self.client.patch(url, data, format='json', **self.header)
+        # Response should succeed because the read-only `user` field is ignored
+        self.assertEqual(response.status_code, 200)
+        token1.refresh_from_db()
+        self.assertEqual(token1.user, user1, "Token's user should not have changed")
+
 
 class ObjectPermissionTest(
     # No GraphQL support for ObjectPermission