prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  We should be able to create new admin users, upgrade existing users to admin
  ## Description
  * `is_superuser` is currently a readonly property in Users APIs.
  * We should be able to set them while an admin is editing a user.
  * Users (including super-users) should not be able to modify it's value for themselves.
  
  
  </issue>
  <code>
  [start of mathesar/api/ui/serializers/users.py]
  1 from django.contrib.auth.password_validation import validate_password
  2 from rest_access_policy import FieldAccessMixin, PermittedPkRelatedField
  3 from rest_framework import serializers
  4 
  5 from mathesar.api.db.permissions.database import DatabaseAccessPolicy
  6 from mathesar.api.db.permissions.schema import SchemaAccessPolicy
  7 from mathesar.api.exceptions.mixins import MathesarErrorMessageMixin
  8 from mathesar.api.exceptions.validation_exceptions.exceptions import IncorrectOldPassword
  9 from mathesar.api.ui.permissions.users import UserAccessPolicy
  10 from mathesar.models.base import Database, Schema
  11 from mathesar.models.users import User, DatabaseRole, SchemaRole
  12 
  13 
  14 class NestedDatabaseRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):
  15     class Meta:
  16         model = DatabaseRole
  17         fields = ['id', 'database', 'role']
  18 
  19 
  20 class NestedSchemaRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):
  21     class Meta:
  22         model = SchemaRole
  23         fields = ['id', 'schema', 'role']
  24 
  25 
  26 class UserSerializer(MathesarErrorMessageMixin, FieldAccessMixin, serializers.ModelSerializer):
  27     database_roles = NestedDatabaseRoleSerializer(many=True, required=False)
  28     schema_roles = NestedSchemaRoleSerializer(many=True, required=False)
  29     access_policy = UserAccessPolicy
  30 
  31     class Meta:
  32         model = User
  33         fields = [
  34             'id',
  35             'full_name',
  36             'short_name',
  37             'username',
  38             'password',
  39             'email',
  40             'is_superuser',
  41             'database_roles',
  42             'schema_roles',
  43         ]
  44         extra_kwargs = {
  45             'password': {'write_only': True},
  46             'is_superuser': {'read_only': True},
  47             'database_roles': {'read_only': True},
  48             'schema_roles': {'read_only': True}
  49         }
  50 
  51     def create(self, validated_data):
  52         password = validated_data.pop('password')
  53         user = User(**validated_data)
  54         user.password_change_needed = True
  55         user.set_password(password)
  56         user.save()
  57         return user
  58 
  59 
  60 class ChangePasswordSerializer(serializers.Serializer):
  61     password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
  62     old_password = serializers.CharField(write_only=True, required=True)
  63 
  64     def validate_old_password(self, value):
  65         user = self.context['request'].user
  66         if user.check_password(value) is True:
  67             return value
  68         raise IncorrectOldPassword(field='old_password')
  69 
  70     def update(self, instance, validated_data):
  71         instance.set_password(validated_data['password'])
  72         instance.save()
  73         return instance
  74 
  75 
  76 class PasswordResetSerializer(MathesarErrorMessageMixin, serializers.Serializer):
  77     password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
  78 
  79 
  80 class DatabaseRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):
  81     class Meta:
  82         model = DatabaseRole
  83         fields = ['id', 'user', 'database', 'role']
  84 
  85     # Restrict the list of databases to which the user has access to create a database role
  86     # Refer https://rsinger86.github.io/drf-access-policy/policy_reuse/ for the usage of `PermittedPkRelatedField`
  87     database = PermittedPkRelatedField(
  88         access_policy=DatabaseAccessPolicy,
  89         queryset=Database.current_objects.all()
  90     )
  91 
  92 
  93 class SchemaRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):
  94     class Meta:
  95         model = SchemaRole
  96         fields = ['id', 'user', 'schema', 'role']
  97 
  98     schema = PermittedPkRelatedField(
  99         access_policy=SchemaAccessPolicy,
  100         queryset=Schema.current_objects.all()
  101     )
  102
  [end of mathesar/api/ui/serializers/users.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/mathesar/api/ui/serializers/users.py b/mathesar/api/ui/serializers/users.py
  --- a/mathesar/api/ui/serializers/users.py
  +++ b/mathesar/api/ui/serializers/users.py
  @@ -43,11 +43,23 @@
           ]
           extra_kwargs = {
               'password': {'write_only': True},
  -            'is_superuser': {'read_only': True},
               'database_roles': {'read_only': True},
               'schema_roles': {'read_only': True}
           }
   
  +    def get_fields(self):
  +        fields = super().get_fields()
  +        request = self.context.get("request", None)
  +        if not hasattr(request, 'parser_context'):
  +            return fields
  +        kwargs = request.parser_context.get('kwargs')
  +        if kwargs:
  +            user_pk = kwargs.get('pk')
  +            if user_pk:
  +                if request.user.id == int(user_pk) or not request.user.is_superuser:
  +                    fields["is_superuser"].read_only = True
  +        return fields
  +
       def create(self, validated_data):
           password = validated_data.pop('password')
           user = User(**validated_data)
  
verification_info: {"golden_diff": "diff --git a/mathesar/api/ui/serializers/users.py b/mathesar/api/ui/serializers/users.py\n--- a/mathesar/api/ui/serializers/users.py\n+++ b/mathesar/api/ui/serializers/users.py\n@@ -43,11 +43,23 @@\n         ]\n         extra_kwargs = {\n             'password': {'write_only': True},\n-            'is_superuser': {'read_only': True},\n             'database_roles': {'read_only': True},\n             'schema_roles': {'read_only': True}\n         }\n \n+    def get_fields(self):\n+        fields = super().get_fields()\n+        request = self.context.get(\"request\", None)\n+        if not hasattr(request, 'parser_context'):\n+            return fields\n+        kwargs = request.parser_context.get('kwargs')\n+        if kwargs:\n+            user_pk = kwargs.get('pk')\n+            if user_pk:\n+                if request.user.id == int(user_pk) or not request.user.is_superuser:\n+                    fields[\"is_superuser\"].read_only = True\n+        return fields\n+\n     def create(self, validated_data):\n         password = validated_data.pop('password')\n         user = User(**validated_data)\n", "issue": "We should be able to create new admin users, upgrade existing users to admin\n## Description\r\n* `is_superuser` is currently a readonly property in Users APIs.\r\n* We should be able to set them while an admin is editing a user.\r\n* Users (including super-users) should not be able to modify it's value for themselves.\r\n\n", "before_files": [{"content": "from django.contrib.auth.password_validation import validate_password\nfrom rest_access_policy import FieldAccessMixin, PermittedPkRelatedField\nfrom rest_framework import serializers\n\nfrom mathesar.api.db.permissions.database import DatabaseAccessPolicy\nfrom mathesar.api.db.permissions.schema import SchemaAccessPolicy\nfrom mathesar.api.exceptions.mixins import MathesarErrorMessageMixin\nfrom mathesar.api.exceptions.validation_exceptions.exceptions import IncorrectOldPassword\nfrom mathesar.api.ui.permissions.users import UserAccessPolicy\nfrom mathesar.models.base import Database, Schema\nfrom mathesar.models.users import User, DatabaseRole, SchemaRole\n\n\nclass NestedDatabaseRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):\n    class Meta:\n        model = DatabaseRole\n        fields = ['id', 'database', 'role']\n\n\nclass NestedSchemaRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):\n    class Meta:\n        model = SchemaRole\n        fields = ['id', 'schema', 'role']\n\n\nclass UserSerializer(MathesarErrorMessageMixin, FieldAccessMixin, serializers.ModelSerializer):\n    database_roles = NestedDatabaseRoleSerializer(many=True, required=False)\n    schema_roles = NestedSchemaRoleSerializer(many=True, required=False)\n    access_policy = UserAccessPolicy\n\n    class Meta:\n        model = User\n        fields = [\n            'id',\n            'full_name',\n            'short_name',\n            'username',\n            'password',\n            'email',\n            'is_superuser',\n            'database_roles',\n            'schema_roles',\n        ]\n        extra_kwargs = {\n            'password': {'write_only': True},\n            'is_superuser': {'read_only': True},\n            'database_roles': {'read_only': True},\n            'schema_roles': {'read_only': True}\n        }\n\n    def create(self, validated_data):\n        password = validated_data.pop('password')\n        user = User(**validated_data)\n        user.password_change_needed = True\n        user.set_password(password)\n        user.save()\n        return user\n\n\nclass ChangePasswordSerializer(serializers.Serializer):\n    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])\n    old_password = serializers.CharField(write_only=True, required=True)\n\n    def validate_old_password(self, value):\n        user = self.context['request'].user\n        if user.check_password(value) is True:\n            return value\n        raise IncorrectOldPassword(field='old_password')\n\n    def update(self, instance, validated_data):\n        instance.set_password(validated_data['password'])\n        instance.save()\n        return instance\n\n\nclass PasswordResetSerializer(MathesarErrorMessageMixin, serializers.Serializer):\n    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])\n\n\nclass DatabaseRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):\n    class Meta:\n        model = DatabaseRole\n        fields = ['id', 'user', 'database', 'role']\n\n    # Restrict the list of databases to which the user has access to create a database role\n    # Refer https://rsinger86.github.io/drf-access-policy/policy_reuse/ for the usage of `PermittedPkRelatedField`\n    database = PermittedPkRelatedField(\n        access_policy=DatabaseAccessPolicy,\n        queryset=Database.current_objects.all()\n    )\n\n\nclass SchemaRoleSerializer(MathesarErrorMessageMixin, serializers.ModelSerializer):\n    class Meta:\n        model = SchemaRole\n        fields = ['id', 'user', 'schema', 'role']\n\n    schema = PermittedPkRelatedField(\n        access_policy=SchemaAccessPolicy,\n        queryset=Schema.current_objects.all()\n    )\n", "path": "mathesar/api/ui/serializers/users.py"}]}