We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
File upload for Indicator Period Data requires Django login
When uploading a photo/file to the /rest/v1/indicator_period_data/nnn/upload_file/ endpoint, a Django login is required, which is not the case for the rest of the API; an API key should be sufficient.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `akvo/rest/views/indicator_period_data.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # Akvo RSR is covered by the GNU Affero General Public License.
4 # See more details in the license.txt file located at the root folder of the Akvo RSR module.
5 # For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
6 
7 
8 from akvo.rsr.models import IndicatorPeriodData, IndicatorPeriodDataComment
9 
10 from ..serializers import (IndicatorPeriodDataSerializer, IndicatorPeriodDataFrameworkSerializer,
11                            IndicatorPeriodDataCommentSerializer)
12 from ..viewsets import PublicProjectViewSet
13 
14 from rest_framework.decorators import api_view, permission_classes
15 from rest_framework.permissions import IsAuthenticated
16 from rest_framework.response import Response
17 
18 
19 class IndicatorPeriodDataViewSet(PublicProjectViewSet):
20     """
21     """
22     queryset = IndicatorPeriodData.objects.all()
23     serializer_class = IndicatorPeriodDataSerializer
24     filter_fields = {
25         'period': ['exact'],
26         'period__indicator': ['exact'],
27         'period__indicator__result': ['exact'],
28         'period__indicator__result__project': ['exact'],
29         'user': ['exact'],
30         'status': ['exact'],
31         'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
32         'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
33         'relative_data': ['exact'],
34         'data': ['exact', 'gt', 'gte', 'lt', 'lte', ],
35         'period_actual_value': ['exact', 'gt', 'gte', 'lt', 'lte', ],
36         'update_method': ['exact']
37     }
38 
39     project_relation = 'period__indicator__result__project__'
40 
41 
42 class IndicatorPeriodDataFrameworkViewSet(PublicProjectViewSet):
43     """
44     """
45     queryset = IndicatorPeriodData.objects.all()
46     serializer_class = IndicatorPeriodDataFrameworkSerializer
47     filter_fields = {
48         'period': ['exact'],
49         'period__indicator': ['exact'],
50         'period__indicator__result': ['exact'],
51         'period__indicator__result__project': ['exact'],
52         'user': ['exact'],
53         'status': ['exact'],
54         'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
55         'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
56         'relative_data': ['exact'],
57         'data': ['exact', 'gt', 'gte', 'lt', 'lte', ],
58         'period_actual_value': ['exact', 'gt', 'gte', 'lt', 'lte', ],
59         'update_method': ['exact']
60     }
61     project_relation = 'period__indicator__result__project__'
62 
63 
64 class IndicatorPeriodDataCommentViewSet(PublicProjectViewSet):
65     """
66     """
67     queryset = IndicatorPeriodDataComment.objects.all()
68     serializer_class = IndicatorPeriodDataCommentSerializer
69     filter_fields = {
70         'data': ['exact'],
71         'data__period': ['exact'],
72         'data__period__indicator': ['exact'],
73         'data__period__indicator__result': ['exact'],
74         'data__period__indicator__result__project': ['exact'],
75         'user': ['exact'],
76         'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
77         'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ]
78     }
79     project_relation = 'period__indicator__result__project__'
80 
81 
82 @api_view(['POST'])
83 @permission_classes((IsAuthenticated, ))
84 def indicator_upload_file(request, pk=None):
85     """
86     Special API call for directly uploading a file.
87 
88     :param request; A Django request object.
89     :param pk; The primary key of an IndicatorPeriodData instance.
90     """
91     update = IndicatorPeriodData.objects.get(pk=pk)
92     upload_file = request.FILES['file']
93 
94     # TODO: Permissions
95     # user = request.user
96 
97     file_type = request.POST.copy()['type']
98     if file_type == 'photo':
99         update.photo = upload_file
100         update.save(update_fields=['photo'])
101         return Response({'file': update.photo.url})
102     elif file_type == 'file':
103         update.file = upload_file
104         update.save(update_fields=['file'])
105         return Response({'file': update.file.url})
106 
107     # TODO: Error response
108     return Response({})
109
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/akvo/rest/views/indicator_period_data.py b/akvo/rest/views/indicator_period_data.py
--- a/akvo/rest/views/indicator_period_data.py
+++ b/akvo/rest/views/indicator_period_data.py
@@ -11,8 +11,10 @@
                            IndicatorPeriodDataCommentSerializer)
 from ..viewsets import PublicProjectViewSet
 
+from django.http import HttpResponseForbidden
+
+from rest_framework import status
 from rest_framework.decorators import api_view, permission_classes
-from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
 
 
@@ -80,7 +82,6 @@
 
 
 @api_view(['POST'])
-@permission_classes((IsAuthenticated, ))
 def indicator_upload_file(request, pk=None):
     """
     Special API call for directly uploading a file.
@@ -91,18 +92,24 @@
     update = IndicatorPeriodData.objects.get(pk=pk)
     upload_file = request.FILES['file']
 
-    # TODO: Permissions
-    # user = request.user
-
-    file_type = request.POST.copy()['type']
-    if file_type == 'photo':
-        update.photo = upload_file
-        update.save(update_fields=['photo'])
-        return Response({'file': update.photo.url})
-    elif file_type == 'file':
-        update.file = upload_file
-        update.save(update_fields=['file'])
-        return Response({'file': update.file.url})
-
-    # TODO: Error response
-    return Response({})
+    # Permissions
+    user = getattr(request, 'user', None)
+    if not user:
+        return Response({'error': 'User is not logged in'}, status=status.HTTP_403_FORBIDDEN)
+
+    if not user.has_perm('rsr.change_project', update.period.indicator.result.project):
+        return Response({'error': 'User has no permission to place an update'},
+                        status=status.HTTP_403_FORBIDDEN)
+
+    try:
+        file_type = request.POST.copy()['type']
+        if file_type == 'photo':
+            update.photo = upload_file
+            update.save(update_fields=['photo'])
+            return Response({'file': update.photo.url})
+        elif file_type == 'file':
+            update.file = upload_file
+            update.save(update_fields=['file'])
+            return Response({'file': update.file.url})
+    except Exception as e:
+        return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

{"golden_diff": "diff --git a/akvo/rest/views/indicator_period_data.py b/akvo/rest/views/indicator_period_data.py\n--- a/akvo/rest/views/indicator_period_data.py\n+++ b/akvo/rest/views/indicator_period_data.py\n@@ -11,8 +11,10 @@\n                            IndicatorPeriodDataCommentSerializer)\n from ..viewsets import PublicProjectViewSet\n \n+from django.http import HttpResponseForbidden\n+\n+from rest_framework import status\n from rest_framework.decorators import api_view, permission_classes\n-from rest_framework.permissions import IsAuthenticated\n from rest_framework.response import Response\n \n \n@@ -80,7 +82,6 @@\n \n \n @api_view(['POST'])\n-@permission_classes((IsAuthenticated, ))\n def indicator_upload_file(request, pk=None):\n     \"\"\"\n     Special API call for directly uploading a file.\n@@ -91,18 +92,24 @@\n     update = IndicatorPeriodData.objects.get(pk=pk)\n     upload_file = request.FILES['file']\n \n-    # TODO: Permissions\n-    # user = request.user\n-\n-    file_type = request.POST.copy()['type']\n-    if file_type == 'photo':\n-        update.photo = upload_file\n-        update.save(update_fields=['photo'])\n-        return Response({'file': update.photo.url})\n-    elif file_type == 'file':\n-        update.file = upload_file\n-        update.save(update_fields=['file'])\n-        return Response({'file': update.file.url})\n-\n-    # TODO: Error response\n-    return Response({})\n+    # Permissions\n+    user = getattr(request, 'user', None)\n+    if not user:\n+        return Response({'error': 'User is not logged in'}, status=status.HTTP_403_FORBIDDEN)\n+\n+    if not user.has_perm('rsr.change_project', update.period.indicator.result.project):\n+        return Response({'error': 'User has no permission to place an update'},\n+                        status=status.HTTP_403_FORBIDDEN)\n+\n+    try:\n+        file_type = request.POST.copy()['type']\n+        if file_type == 'photo':\n+            update.photo = upload_file\n+            update.save(update_fields=['photo'])\n+            return Response({'file': update.photo.url})\n+        elif file_type == 'file':\n+            update.file = upload_file\n+            update.save(update_fields=['file'])\n+            return Response({'file': update.file.url})\n+    except Exception as e:\n+        return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)\n", "issue": "File upload for Indicator Period Data requires Django login\nWhen uploading a photo/file to the /rest/v1/indicator_period_data/nnn/upload_file/ endpoint, a Django login is required, which is not the case for the rest of the API; an API key should be sufficient.\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo RSR is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\n\nfrom akvo.rsr.models import IndicatorPeriodData, IndicatorPeriodDataComment\n\nfrom ..serializers import (IndicatorPeriodDataSerializer, IndicatorPeriodDataFrameworkSerializer,\n                           IndicatorPeriodDataCommentSerializer)\nfrom ..viewsets import PublicProjectViewSet\n\nfrom rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\n\n\nclass IndicatorPeriodDataViewSet(PublicProjectViewSet):\n    \"\"\"\n    \"\"\"\n    queryset = IndicatorPeriodData.objects.all()\n    serializer_class = IndicatorPeriodDataSerializer\n    filter_fields = {\n        'period': ['exact'],\n        'period__indicator': ['exact'],\n        'period__indicator__result': ['exact'],\n        'period__indicator__result__project': ['exact'],\n        'user': ['exact'],\n        'status': ['exact'],\n        'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'relative_data': ['exact'],\n        'data': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'period_actual_value': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'update_method': ['exact']\n    }\n\n    project_relation = 'period__indicator__result__project__'\n\n\nclass IndicatorPeriodDataFrameworkViewSet(PublicProjectViewSet):\n    \"\"\"\n    \"\"\"\n    queryset = IndicatorPeriodData.objects.all()\n    serializer_class = IndicatorPeriodDataFrameworkSerializer\n    filter_fields = {\n        'period': ['exact'],\n        'period__indicator': ['exact'],\n        'period__indicator__result': ['exact'],\n        'period__indicator__result__project': ['exact'],\n        'user': ['exact'],\n        'status': ['exact'],\n        'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'relative_data': ['exact'],\n        'data': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'period_actual_value': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'update_method': ['exact']\n    }\n    project_relation = 'period__indicator__result__project__'\n\n\nclass IndicatorPeriodDataCommentViewSet(PublicProjectViewSet):\n    \"\"\"\n    \"\"\"\n    queryset = IndicatorPeriodDataComment.objects.all()\n    serializer_class = IndicatorPeriodDataCommentSerializer\n    filter_fields = {\n        'data': ['exact'],\n        'data__period': ['exact'],\n        'data__period__indicator': ['exact'],\n        'data__period__indicator__result': ['exact'],\n        'data__period__indicator__result__project': ['exact'],\n        'user': ['exact'],\n        'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ]\n    }\n    project_relation = 'period__indicator__result__project__'\n\n\n@api_view(['POST'])\n@permission_classes((IsAuthenticated, ))\ndef indicator_upload_file(request, pk=None):\n    \"\"\"\n    Special API call for directly uploading a file.\n\n    :param request; A Django request object.\n    :param pk; The primary key of an IndicatorPeriodData instance.\n    \"\"\"\n    update = IndicatorPeriodData.objects.get(pk=pk)\n    upload_file = request.FILES['file']\n\n    # TODO: Permissions\n    # user = request.user\n\n    file_type = request.POST.copy()['type']\n    if file_type == 'photo':\n        update.photo = upload_file\n        update.save(update_fields=['photo'])\n        return Response({'file': update.photo.url})\n    elif file_type == 'file':\n        update.file = upload_file\n        update.save(update_fields=['file'])\n        return Response({'file': update.file.url})\n\n    # TODO: Error response\n    return Response({})\n", "path": "akvo/rest/views/indicator_period_data.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo RSR is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\n\nfrom akvo.rsr.models import IndicatorPeriodData, IndicatorPeriodDataComment\n\nfrom ..serializers import (IndicatorPeriodDataSerializer, IndicatorPeriodDataFrameworkSerializer,\n                           IndicatorPeriodDataCommentSerializer)\nfrom ..viewsets import PublicProjectViewSet\n\nfrom django.http import HttpResponseForbidden\n\nfrom rest_framework import status\nfrom rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.response import Response\n\n\nclass IndicatorPeriodDataViewSet(PublicProjectViewSet):\n    \"\"\"\n    \"\"\"\n    queryset = IndicatorPeriodData.objects.all()\n    serializer_class = IndicatorPeriodDataSerializer\n    filter_fields = {\n        'period': ['exact'],\n        'period__indicator': ['exact'],\n        'period__indicator__result': ['exact'],\n        'period__indicator__result__project': ['exact'],\n        'user': ['exact'],\n        'status': ['exact'],\n        'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'relative_data': ['exact'],\n        'data': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'period_actual_value': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'update_method': ['exact']\n    }\n\n    project_relation = 'period__indicator__result__project__'\n\n\nclass IndicatorPeriodDataFrameworkViewSet(PublicProjectViewSet):\n    \"\"\"\n    \"\"\"\n    queryset = IndicatorPeriodData.objects.all()\n    serializer_class = IndicatorPeriodDataFrameworkSerializer\n    filter_fields = {\n        'period': ['exact'],\n        'period__indicator': ['exact'],\n        'period__indicator__result': ['exact'],\n        'period__indicator__result__project': ['exact'],\n        'user': ['exact'],\n        'status': ['exact'],\n        'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'relative_data': ['exact'],\n        'data': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'period_actual_value': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'update_method': ['exact']\n    }\n    project_relation = 'period__indicator__result__project__'\n\n\nclass IndicatorPeriodDataCommentViewSet(PublicProjectViewSet):\n    \"\"\"\n    \"\"\"\n    queryset = IndicatorPeriodDataComment.objects.all()\n    serializer_class = IndicatorPeriodDataCommentSerializer\n    filter_fields = {\n        'data': ['exact'],\n        'data__period': ['exact'],\n        'data__period__indicator': ['exact'],\n        'data__period__indicator__result': ['exact'],\n        'data__period__indicator__result__project': ['exact'],\n        'user': ['exact'],\n        'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],\n        'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ]\n    }\n    project_relation = 'period__indicator__result__project__'\n\n\n@api_view(['POST'])\ndef indicator_upload_file(request, pk=None):\n    \"\"\"\n    Special API call for directly uploading a file.\n\n    :param request; A Django request object.\n    :param pk; The primary key of an IndicatorPeriodData instance.\n    \"\"\"\n    update = IndicatorPeriodData.objects.get(pk=pk)\n    upload_file = request.FILES['file']\n\n    # Permissions\n    user = getattr(request, 'user', None)\n    if not user:\n        return Response({'error': 'User is not logged in'}, status=status.HTTP_403_FORBIDDEN)\n\n    if not user.has_perm('rsr.change_project', update.period.indicator.result.project):\n        return Response({'error': 'User has no permission to place an update'},\n                        status=status.HTTP_403_FORBIDDEN)\n\n    try:\n        file_type = request.POST.copy()['type']\n        if file_type == 'photo':\n            update.photo = upload_file\n            update.save(update_fields=['photo'])\n            return Response({'file': update.photo.url})\n        elif file_type == 'file':\n            update.file = upload_file\n            update.save(update_fields=['file'])\n            return Response({'file': update.file.url})\n    except Exception as e:\n        return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)\n", "path": "akvo/rest/views/indicator_period_data.py"}]}