prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Sales API uses TokenHasScopeForMethod but no scopes per method are provided
  ### Describe the change
  The sales API uses some IsAuthenticatedOrTokenHasScopeForMethod permission classes, but no scopes per method are provided
  
  ### Motivation
  Simpler code
  
  ### Current implementation
  See above
  
  ### Suggested implementation
  Use IsAuthenticatedOrTokenHasScope, or specify scope per method 
  
  
  
  </issue>
  <code>
  [start of website/sales/api/v2/admin/views.py]
  1 from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
  2 from rest_framework import filters, exceptions
  3 from rest_framework.exceptions import PermissionDenied
  4 from rest_framework.generics import get_object_or_404
  5 from rest_framework.permissions import DjangoModelPermissions
  6 
  7 from sales.api.v2.admin.permissions import IsManager
  8 from sales.api.v2.admin.serializers.order import OrderSerializer, OrderListSerializer
  9 from sales.api.v2.admin.serializers.shift import ShiftSerializer
  10 from sales.models.order import Order
  11 from sales.models.shift import Shift
  12 from thaliawebsite.api.v2.admin import (
  13     AdminCreateAPIView,
  14     AdminListAPIView,
  15     AdminRetrieveAPIView,
  16     AdminUpdateAPIView,
  17     AdminDestroyAPIView,
  18 )
  19 from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod
  20 
  21 
  22 class ShiftListView(AdminListAPIView):
  23     """Returns an overview of all sales shifts."""
  24 
  25     serializer_class = ShiftSerializer
  26     queryset = Shift.objects.all()
  27     filter_backends = (
  28         filters.OrderingFilter,
  29         filters.SearchFilter,
  30     )
  31     ordering_fields = ("start", "end")
  32     permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoModelPermissions]
  33     required_scopes = ["sales:admin"]
  34 
  35     def get_queryset(self):
  36         queryset = super().get_queryset().filter(locked=False)
  37 
  38         if not self.request.member:
  39             queryset = queryset.none()
  40         elif not self.request.member.has_perm("sales.override_manager"):
  41             queryset = queryset.filter(
  42                 managers__in=self.request.member.get_member_groups()
  43             ).distinct()
  44 
  45         queryset = queryset.select_properties(
  46             "active",
  47             "total_revenue",
  48             "total_revenue_paid",
  49             "num_orders",
  50             "num_orders_paid",
  51         )
  52         queryset = queryset.prefetch_related("event", "product_list")
  53         queryset = queryset.prefetch_related("orders__order_items",)
  54         return queryset
  55 
  56 
  57 class ShiftDetailView(AdminRetrieveAPIView):
  58     serializer_class = ShiftSerializer
  59     queryset = Shift.objects.all()
  60     permission_classes = [
  61         IsAuthenticatedOrTokenHasScope,
  62         DjangoModelPermissions,
  63         IsManager,
  64     ]
  65     required_scopes = ["sales:admin"]
  66 
  67 
  68 class OrderListView(AdminListAPIView, AdminCreateAPIView):
  69     method_serializer_classes = {
  70         ("GET",): OrderListSerializer,
  71         ("POST",): OrderSerializer,
  72     }
  73     permission_classes = [
  74         IsAuthenticatedOrTokenHasScopeForMethod,
  75         DjangoModelPermissions,
  76         IsManager,
  77     ]
  78     required_scopes = ["sales:admin"]
  79     shift_lookup_field = "pk"
  80 
  81     def get_serializer_class(self):
  82         for methods, serializer_cls in self.method_serializer_classes.items():
  83             if self.request.method in methods:
  84                 return serializer_cls
  85         raise exceptions.MethodNotAllowed(self.request.method)
  86 
  87     def create(self, request, *args, **kwargs):
  88         shift = Shift.objects.get(pk=kwargs["pk"])
  89         if shift.locked:
  90             raise PermissionDenied
  91 
  92         return super(OrderListView, self).create(request, args, kwargs)
  93 
  94     def get_queryset(self):
  95         queryset = Order.objects.all()
  96 
  97         pk = self.kwargs.get("pk")
  98         if pk:
  99             queryset = queryset.filter(shift=pk)
  100 
  101         queryset = queryset.select_properties(
  102             "total_amount", "subtotal", "num_items", "age_restricted"
  103         )
  104         queryset = queryset.prefetch_related(
  105             "shift", "shift__event", "shift__product_list"
  106         )
  107         queryset = queryset.prefetch_related(
  108             "order_items", "order_items__product", "order_items__product__product"
  109         )
  110         queryset = queryset.prefetch_related("payment")
  111         return queryset
  112 
  113     def get_serializer_context(self):
  114         context = super(OrderListView, self).get_serializer_context()
  115         pk = self.kwargs.get("pk")
  116         if pk:
  117             shift = get_object_or_404(Shift, pk=self.kwargs.get("pk"))
  118             context.update({"shift": shift})
  119         return context
  120 
  121 
  122 class OrderDetailView(AdminRetrieveAPIView, AdminUpdateAPIView, AdminDestroyAPIView):
  123     serializer_class = OrderSerializer
  124     queryset = Order.objects.all()
  125     permission_classes = [
  126         IsAuthenticatedOrTokenHasScopeForMethod,
  127         DjangoModelPermissions,
  128         IsManager,
  129     ]
  130     required_scopes = ["sales:admin"]
  131 
  132     def get_queryset(self):
  133         queryset = super().get_queryset()
  134 
  135         if not self.request.member:
  136             queryset = queryset.none()
  137         elif not self.request.member.has_perm("sales.override_manager"):
  138             queryset = queryset.filter(
  139                 shift__managers__in=self.request.member.get_member_groups()
  140             ).distinct()
  141 
  142         queryset = queryset.select_properties(
  143             "total_amount", "subtotal", "num_items", "age_restricted"
  144         )
  145         queryset = queryset.prefetch_related(
  146             "shift", "shift__event", "shift__product_list"
  147         )
  148         queryset = queryset.prefetch_related(
  149             "order_items", "order_items__product", "order_items__product__product"
  150         )
  151         queryset = queryset.prefetch_related("payment")
  152         return queryset
  153
  [end of website/sales/api/v2/admin/views.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/website/sales/api/v2/admin/views.py b/website/sales/api/v2/admin/views.py
  --- a/website/sales/api/v2/admin/views.py
  +++ b/website/sales/api/v2/admin/views.py
  @@ -16,7 +16,6 @@
       AdminUpdateAPIView,
       AdminDestroyAPIView,
   )
  -from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod
   
   
   class ShiftListView(AdminListAPIView):
  @@ -71,7 +70,7 @@
           ("POST",): OrderSerializer,
       }
       permission_classes = [
  -        IsAuthenticatedOrTokenHasScopeForMethod,
  +        IsAuthenticatedOrTokenHasScope,
           DjangoModelPermissions,
           IsManager,
       ]
  @@ -123,7 +122,7 @@
       serializer_class = OrderSerializer
       queryset = Order.objects.all()
       permission_classes = [
  -        IsAuthenticatedOrTokenHasScopeForMethod,
  +        IsAuthenticatedOrTokenHasScope,
           DjangoModelPermissions,
           IsManager,
       ]
  
verification_info: {"golden_diff": "diff --git a/website/sales/api/v2/admin/views.py b/website/sales/api/v2/admin/views.py\n--- a/website/sales/api/v2/admin/views.py\n+++ b/website/sales/api/v2/admin/views.py\n@@ -16,7 +16,6 @@\n     AdminUpdateAPIView,\n     AdminDestroyAPIView,\n )\n-from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod\n \n \n class ShiftListView(AdminListAPIView):\n@@ -71,7 +70,7 @@\n         (\"POST\",): OrderSerializer,\n     }\n     permission_classes = [\n-        IsAuthenticatedOrTokenHasScopeForMethod,\n+        IsAuthenticatedOrTokenHasScope,\n         DjangoModelPermissions,\n         IsManager,\n     ]\n@@ -123,7 +122,7 @@\n     serializer_class = OrderSerializer\n     queryset = Order.objects.all()\n     permission_classes = [\n-        IsAuthenticatedOrTokenHasScopeForMethod,\n+        IsAuthenticatedOrTokenHasScope,\n         DjangoModelPermissions,\n         IsManager,\n     ]\n", "issue": "Sales API uses TokenHasScopeForMethod but no scopes per method are provided\n### Describe the change\r\nThe sales API uses some IsAuthenticatedOrTokenHasScopeForMethod permission classes, but no scopes per method are provided\r\n\r\n### Motivation\r\nSimpler code\r\n\r\n### Current implementation\r\nSee above\r\n\r\n### Suggested implementation\r\nUse IsAuthenticatedOrTokenHasScope, or specify scope per method \r\n\r\n\n", "before_files": [{"content": "from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope\nfrom rest_framework import filters, exceptions\nfrom rest_framework.exceptions import PermissionDenied\nfrom rest_framework.generics import get_object_or_404\nfrom rest_framework.permissions import DjangoModelPermissions\n\nfrom sales.api.v2.admin.permissions import IsManager\nfrom sales.api.v2.admin.serializers.order import OrderSerializer, OrderListSerializer\nfrom sales.api.v2.admin.serializers.shift import ShiftSerializer\nfrom sales.models.order import Order\nfrom sales.models.shift import Shift\nfrom thaliawebsite.api.v2.admin import (\n    AdminCreateAPIView,\n    AdminListAPIView,\n    AdminRetrieveAPIView,\n    AdminUpdateAPIView,\n    AdminDestroyAPIView,\n)\nfrom thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod\n\n\nclass ShiftListView(AdminListAPIView):\n    \"\"\"Returns an overview of all sales shifts.\"\"\"\n\n    serializer_class = ShiftSerializer\n    queryset = Shift.objects.all()\n    filter_backends = (\n        filters.OrderingFilter,\n        filters.SearchFilter,\n    )\n    ordering_fields = (\"start\", \"end\")\n    permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoModelPermissions]\n    required_scopes = [\"sales:admin\"]\n\n    def get_queryset(self):\n        queryset = super().get_queryset().filter(locked=False)\n\n        if not self.request.member:\n            queryset = queryset.none()\n        elif not self.request.member.has_perm(\"sales.override_manager\"):\n            queryset = queryset.filter(\n                managers__in=self.request.member.get_member_groups()\n            ).distinct()\n\n        queryset = queryset.select_properties(\n            \"active\",\n            \"total_revenue\",\n            \"total_revenue_paid\",\n            \"num_orders\",\n            \"num_orders_paid\",\n        )\n        queryset = queryset.prefetch_related(\"event\", \"product_list\")\n        queryset = queryset.prefetch_related(\"orders__order_items\",)\n        return queryset\n\n\nclass ShiftDetailView(AdminRetrieveAPIView):\n    serializer_class = ShiftSerializer\n    queryset = Shift.objects.all()\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScope,\n        DjangoModelPermissions,\n        IsManager,\n    ]\n    required_scopes = [\"sales:admin\"]\n\n\nclass OrderListView(AdminListAPIView, AdminCreateAPIView):\n    method_serializer_classes = {\n        (\"GET\",): OrderListSerializer,\n        (\"POST\",): OrderSerializer,\n    }\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScopeForMethod,\n        DjangoModelPermissions,\n        IsManager,\n    ]\n    required_scopes = [\"sales:admin\"]\n    shift_lookup_field = \"pk\"\n\n    def get_serializer_class(self):\n        for methods, serializer_cls in self.method_serializer_classes.items():\n            if self.request.method in methods:\n                return serializer_cls\n        raise exceptions.MethodNotAllowed(self.request.method)\n\n    def create(self, request, *args, **kwargs):\n        shift = Shift.objects.get(pk=kwargs[\"pk\"])\n        if shift.locked:\n            raise PermissionDenied\n\n        return super(OrderListView, self).create(request, args, kwargs)\n\n    def get_queryset(self):\n        queryset = Order.objects.all()\n\n        pk = self.kwargs.get(\"pk\")\n        if pk:\n            queryset = queryset.filter(shift=pk)\n\n        queryset = queryset.select_properties(\n            \"total_amount\", \"subtotal\", \"num_items\", \"age_restricted\"\n        )\n        queryset = queryset.prefetch_related(\n            \"shift\", \"shift__event\", \"shift__product_list\"\n        )\n        queryset = queryset.prefetch_related(\n            \"order_items\", \"order_items__product\", \"order_items__product__product\"\n        )\n        queryset = queryset.prefetch_related(\"payment\")\n        return queryset\n\n    def get_serializer_context(self):\n        context = super(OrderListView, self).get_serializer_context()\n        pk = self.kwargs.get(\"pk\")\n        if pk:\n            shift = get_object_or_404(Shift, pk=self.kwargs.get(\"pk\"))\n            context.update({\"shift\": shift})\n        return context\n\n\nclass OrderDetailView(AdminRetrieveAPIView, AdminUpdateAPIView, AdminDestroyAPIView):\n    serializer_class = OrderSerializer\n    queryset = Order.objects.all()\n    permission_classes = [\n        IsAuthenticatedOrTokenHasScopeForMethod,\n        DjangoModelPermissions,\n        IsManager,\n    ]\n    required_scopes = [\"sales:admin\"]\n\n    def get_queryset(self):\n        queryset = super().get_queryset()\n\n        if not self.request.member:\n            queryset = queryset.none()\n        elif not self.request.member.has_perm(\"sales.override_manager\"):\n            queryset = queryset.filter(\n                shift__managers__in=self.request.member.get_member_groups()\n            ).distinct()\n\n        queryset = queryset.select_properties(\n            \"total_amount\", \"subtotal\", \"num_items\", \"age_restricted\"\n        )\n        queryset = queryset.prefetch_related(\n            \"shift\", \"shift__event\", \"shift__product_list\"\n        )\n        queryset = queryset.prefetch_related(\n            \"order_items\", \"order_items__product\", \"order_items__product__product\"\n        )\n        queryset = queryset.prefetch_related(\"payment\")\n        return queryset\n", "path": "website/sales/api/v2/admin/views.py"}]}