We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
hide rating form for app owners
Currently app owners also see app rating forms for their own apps. While it's statistically irrelevant people seem to think that it's a way to cheat the system. We should therefore simply hide the form and button for owners.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nextcloudappstore/core/forms.py`
Content:
```
1 from django.forms import Form, CharField, Textarea, ChoiceField, RadioSelect, \
2     BooleanField, TextInput
3 from django.utils.translation import ugettext_lazy as _  # type: ignore
4 
5 from nextcloudappstore.core.models import App, AppRating
6 
7 RATING_CHOICES = (
8     (0.0, _('Bad')),
9     (0.5, _('Ok')),
10     (1.0, _('Good'))
11 )
12 
13 
14 class AppReleaseUploadForm(Form):
15     download = CharField(label=_('Download link (tar.gz)'), max_length=256,
16                          widget=TextInput(attrs={'required': 'required'}))
17     signature = CharField(widget=Textarea(attrs={'required': 'required'}),
18                           label=_('SHA512 signature'),
19                           help_text=_(
20                               'Can be generated by executing the '
21                               'following command: <b>openssl dgst -sha512 '
22                               '-sign ~/.nextcloud/certificates/APP_ID.key '
23                               '/path/to/app.tar.gz | openssl base64</b>'))
24     nightly = BooleanField(label=_('Nightly'), required=False)
25     safe_help_fields = ['signature']
26 
27 
28 class AppRegisterForm(Form):
29     certificate = CharField(
30         widget=Textarea(attrs={'required': 'required'}),
31         label=_('Public certificate'),
32         help_text=_(
33             'Usually stored in ~/.nextcloud/certificates/APP_ID.crt where '
34             'APP_ID is your app\'s id. If you do not have a certificate you '
35             'need to create a certificate sign request (CSR) first which '
36             'should be posted on the <a '
37             'href="https://github.com/nextcloud/app-certificate-requests" '
38             'rel="noreferrer noopener">certificate repository</a> (follow '
39             'the README). You can generate the CSR by executing the '
40             'following command: <b>openssl req -nodes -newkey rsa:4096 '
41             '-keyout APP_ID.key -out APP_ID.csr -subj "/CN=APP_ID"</b>'))
42     signature = CharField(widget=Textarea(attrs={'required': 'required'}),
43                           label=_('SHA512 signature over your app\'s id'),
44                           help_text=_(
45                               'Can be generated by executing the '
46                               'following '
47                               'command: <b>echo -n "APP_ID" | openssl dgst '
48                               '-sha512 -sign '
49                               '~/.nextcloud/certificates/APP_ID.key | '
50                               'openssl base64</b>'))
51     safe_help_fields = ['certificate', 'signature']
52 
53 
54 class AppRatingForm(Form):
55     def __init__(self, *args, **kwargs):
56         self._id = kwargs.pop('id', None)
57         self._user = kwargs.pop('user', None)
58         self._language_code = kwargs.pop('language_code', None)
59         super().__init__(*args, **kwargs)
60 
61     rating = ChoiceField(initial=0.5, choices=RATING_CHOICES,
62                          widget=RadioSelect)
63     comment = CharField(widget=Textarea, required=False,
64                         label=_('Review'))
65 
66     class Meta:
67         fields = ('rating', 'comment')
68 
69     def save(self):
70         app = App.objects.get(id=self._id)
71         app_rating, created = AppRating.objects.get_or_create(user=self._user,
72                                                               app=app)
73         app_rating.rating = self.cleaned_data['rating']
74         app_rating.set_current_language(self._language_code)
75         app_rating.comment = self.cleaned_data['comment']
76         app_rating.save()
77
```

Path: `nextcloudappstore/core/views.py`
Content:
```
1 from urllib.parse import urlencode
2 
3 from django.conf import settings
4 from django.contrib.auth.mixins import LoginRequiredMixin
5 from django.contrib.auth.models import User
6 from django.core.exceptions import ObjectDoesNotExist
7 from django.db.models import Q
8 from django.http import HttpResponse
9 from django.shortcuts import get_object_or_404, redirect
10 from django.utils.functional import cached_property
11 from django.utils.translation import get_language, get_language_info
12 from django.views.decorators.http import etag
13 from django.views.generic import FormView
14 from django.views.generic.base import TemplateView
15 from django.views.generic.detail import DetailView
16 from django.views.generic.list import ListView
17 from rest_framework.generics import ListAPIView
18 from semantic_version import Version
19 
20 from nextcloudappstore.core.api.v1.serializers import AppRatingSerializer
21 from nextcloudappstore.core.caching import app_etag
22 from nextcloudappstore.core.forms import AppRatingForm, AppReleaseUploadForm, \
23     AppRegisterForm
24 from nextcloudappstore.core.models import App, Category, AppRating
25 from nextcloudappstore.core.scaffolding.archive import build_archive
26 from nextcloudappstore.core.scaffolding.forms import AppScaffoldingForm
27 from nextcloudappstore.core.versioning import pad_min_version
28 
29 
30 @etag(app_etag)
31 def app_description(request, id):
32     app = get_object_or_404(App, id=id)
33     return HttpResponse(app.description, content_type='text/plain')
34 
35 
36 class AppRatingApi(ListAPIView):
37     serializer_class = AppRatingSerializer
38 
39     def get_queryset(self):
40         id = self.kwargs.get('id')
41         app = get_object_or_404(App, id=id)
42         return AppRating.objects.language(self.request.LANGUAGE_CODE).filter(
43             app=app)
44 
45 
46 class LegalNoticeView(TemplateView):
47     template_name = 'legal.html'
48 
49 
50 class AppDetailView(DetailView):
51     queryset = App.objects.prefetch_related('releases', 'screenshots', 'owner',
52                                             'co_maintainers')
53     template_name = 'app/detail.html'
54     slug_field = 'id'
55     slug_url_kwarg = 'id'
56 
57     def post(self, request, id):
58         form = AppRatingForm(request.POST, id=id, user=request.user,
59                              language_code=request.LANGUAGE_CODE)
60         # there is no way that a rating can be invalid by default
61         if form.is_valid() and request.user.is_authenticated:
62             form.save()
63         return redirect('app-detail', id=id)
64 
65     def get_context_data(self, **kwargs):
66         context = super().get_context_data(**kwargs)
67         context['rating_form'] = AppRatingForm()
68         context['user_has_rated_app'] = False
69         if self.request.user.is_authenticated:
70             try:
71                 app_rating = AppRating.objects.get(user=self.request.user,
72                                                    app=context['app'])
73                 # when accessing an empty comment django-parler tries to
74                 # fall back to the default language. However for comments
75                 # the default (English) does not always exist. Unfortunately
76                 # it throws the same exception as non existing models,
77                 # so we need to access it beforehand
78                 try:
79                     comment = app_rating.comment
80                 except AppRating.DoesNotExist:
81                     comment = ''
82 
83                 context['rating_form'] = AppRatingForm(initial={
84                     'rating': app_rating.rating,
85                     'comment': comment
86                 })
87                 context['user_has_rated_app'] = True
88             except AppRating.DoesNotExist:
89                 pass
90         context['categories'] = Category.objects.prefetch_related(
91             'translations').all()
92         context['latest_releases_by_platform_v'] = \
93             self.object.latest_releases_by_platform_v()
94         return context
95 
96 
97 class AppReleasesView(DetailView):
98     queryset = App.objects.prefetch_related(
99         'releases',
100         'releases__databases',
101         'releases__licenses',
102         'releases__phpextensiondependencies__php_extension',
103         'releases__databasedependencies__database',
104         'releases__shell_commands'
105     )
106     template_name = 'app/releases.html'
107     slug_field = 'id'
108     slug_url_kwarg = 'id'
109 
110     def get_context_data(self, **kwargs):
111         context = super().get_context_data(**kwargs)
112         context['categories'] = Category.objects.prefetch_related(
113             'translations').all()
114 
115         releases = self.object.releases_by_platform_v()
116         nightlies = self.object.nightly_releases_by_platform_v()
117         versions = set(list(releases.keys()) + list(nightlies.keys()))
118         all_releases = list(map(
119             lambda v: (v, releases.get(v, []) + nightlies.get(v, [])),
120             versions))
121         context['releases_by_platform_v'] = \
122             self._sort_by_platform_v(all_releases)
123 
124         return context
125 
126     def _sort_by_platform_v(self, releases_by_platform, reverse=True):
127         """Sorts a list of tuples like (<platform version>, [releases]) by
128         platform version.
129 
130         :param releases_by_platform: A list of tuples.
131         :param reverse: Descending order if True, ascending otherwise.
132         :return sorted list of tuples.
133         """
134 
135         return sorted(releases_by_platform, reverse=reverse,
136                       key=lambda v: Version(pad_min_version(v[0])))
137 
138 
139 class CategoryAppListView(ListView):
140     model = App
141     template_name = 'app/list.html'
142     allow_empty = True
143 
144     def get_queryset(self):
145         order_by = self.request.GET.get('order_by', 'rating_overall')
146         ordering = self.request.GET.get('ordering', 'desc')
147         featured = self.request.GET.get('featured', False)
148         maintainer = self.request.GET.get('maintainer', False)
149         sort_columns = []
150 
151         allowed_order_by = {'name', 'last_release', 'rating_overall',
152                             'rating_recent'}
153         if order_by in allowed_order_by:
154             if order_by == 'name':
155                 order_by = 'translations__name'
156             if ordering == 'desc':
157                 sort_columns.append('-' + order_by)
158             else:
159                 sort_columns.append(order_by)
160 
161         lang = get_language_info(get_language())['code']
162         category_id = self.kwargs['id']
163         queryset = App.objects.search(self.search_terms, lang).order_by(
164             *sort_columns).filter(releases__gt=0)
165         if maintainer:
166             try:
167                 user = User.objects.get_by_natural_key(maintainer)
168                 queryset = queryset.filter(Q(owner=user) |
169                                            Q(co_maintainers=user))
170             except ObjectDoesNotExist:
171                 return queryset.none()
172         if category_id:
173             queryset = queryset.filter(categories__id=category_id)
174         if featured == "true":
175             queryset = queryset.filter(featured=True)
176         return queryset.prefetch_related('screenshots', 'translations')
177 
178     def get_context_data(self, **kwargs):
179         context = super().get_context_data(**kwargs)
180         context['categories'] = Category.objects.prefetch_related(
181             'translations').all()
182         category_id = self.kwargs['id']
183         if category_id:
184             context['current_category'] = Category.objects.get(id=category_id)
185         if self.search_terms:
186             context['search_query'] = ' '.join(self.search_terms)
187         context['url_params'] = self.url_params
188         return context
189 
190     @cached_property
191     def url_params(self):
192         """URL encoded strings with the GET params of the last request.
193 
194         Intended for preserving GET params upon clicking a link by including
195         one (and only one) of these strings in the "href" attribute.
196 
197         The parameters are divided into three groups: search, filters and
198         ordering. In addition to these three, the returned dict also contains
199         some combinations of them, as specified by the dict keys.
200 
201         No leading "?" or "&".
202 
203         :return dict with URL encoded strings.
204         """
205 
206         search = self._url_params_str('search')
207         filters = self._url_params_str('featured', 'maintainer')
208         ordering = self._url_params_str('order_by', 'ordering')
209 
210         return {
211             'search': search,
212             'filters': filters,
213             'ordering': ordering,
214             'search_filters': self._join_url_params_strs(search, filters),
215             'filters_ordering': self._join_url_params_strs(filters, ordering),
216         }
217 
218     def _url_params_str(self, *params):
219         args = map(lambda param: (param, self.request.GET.get(param, '')),
220                    params)
221         present_args = filter(lambda a: a[1], args)
222         return urlencode(dict(present_args))
223 
224     def _join_url_params_strs(self, *strings):
225         return '&'.join(filter(None, strings))
226 
227     @cached_property
228     def search_terms(self):
229         return self.request.GET.get('search', '').strip().split()
230 
231 
232 class AppUploadView(LoginRequiredMixin, TemplateView):
233     template_name = 'app/upload.html'
234 
235     def get_context_data(self, **kwargs):
236         context = super().get_context_data(**kwargs)
237         context['form'] = AppReleaseUploadForm()
238         return context
239 
240 
241 class AppScaffoldingView(FormView):
242     template_name = 'app/scaffold.html'
243     form_class = AppScaffoldingForm
244 
245     def get_initial(self):
246         init = {
247             'platform': settings.CURRENT_PLATFORM_STABLE_VERSION,
248             'categories': ('tools',)
249         }
250         if self.request.user.is_authenticated:
251             user = self.request.user
252             init['author_name'] = '%s %s' % (user.first_name, user.last_name)
253             init['author_email'] = user.email
254         return init
255 
256     def form_valid(self, form):
257         buffer = build_archive(form.cleaned_data)
258         response = HttpResponse(content_type='application/tar+gzip')
259         response['Content-Disposition'] = 'attachment; filename="app.tar.gz"'
260         value = buffer.getvalue()
261         buffer.close()
262         response.write(value)
263         return response
264 
265 
266 class AppRegisterView(LoginRequiredMixin, TemplateView):
267     template_name = 'app/register.html'
268 
269     def get_context_data(self, **kwargs):
270         context = super().get_context_data(**kwargs)
271         context['form'] = AppRegisterForm()
272         return context
273
```
--- 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/nextcloudappstore/core/forms.py b/nextcloudappstore/core/forms.py
--- a/nextcloudappstore/core/forms.py
+++ b/nextcloudappstore/core/forms.py
@@ -61,7 +61,7 @@
     rating = ChoiceField(initial=0.5, choices=RATING_CHOICES,
                          widget=RadioSelect)
     comment = CharField(widget=Textarea, required=False,
-                        label=_('Review'))
+                        label=_('Comment'))
 
     class Meta:
         fields = ('rating', 'comment')
diff --git a/nextcloudappstore/core/views.py b/nextcloudappstore/core/views.py
--- a/nextcloudappstore/core/views.py
+++ b/nextcloudappstore/core/views.py
@@ -80,7 +80,7 @@
                 except AppRating.DoesNotExist:
                     comment = ''
 
-                context['rating_form'] = AppRatingForm(initial={
+                context['rating_form'] = AppRatingForm({
                     'rating': app_rating.rating,
                     'comment': comment
                 })

{"golden_diff": "diff --git a/nextcloudappstore/core/forms.py b/nextcloudappstore/core/forms.py\n--- a/nextcloudappstore/core/forms.py\n+++ b/nextcloudappstore/core/forms.py\n@@ -61,7 +61,7 @@\n     rating = ChoiceField(initial=0.5, choices=RATING_CHOICES,\n                          widget=RadioSelect)\n     comment = CharField(widget=Textarea, required=False,\n-                        label=_('Review'))\n+                        label=_('Comment'))\n \n     class Meta:\n         fields = ('rating', 'comment')\ndiff --git a/nextcloudappstore/core/views.py b/nextcloudappstore/core/views.py\n--- a/nextcloudappstore/core/views.py\n+++ b/nextcloudappstore/core/views.py\n@@ -80,7 +80,7 @@\n                 except AppRating.DoesNotExist:\n                     comment = ''\n \n-                context['rating_form'] = AppRatingForm(initial={\n+                context['rating_form'] = AppRatingForm({\n                     'rating': app_rating.rating,\n                     'comment': comment\n                 })\n", "issue": "hide rating form for app owners\nCurrently app owners also see app rating forms for their own apps. While it's statistically irrelevant people seem to think that it's a way to cheat the system. We should therefore simply hide the form and button for owners.\n\n", "before_files": [{"content": "from django.forms import Form, CharField, Textarea, ChoiceField, RadioSelect, \\\n    BooleanField, TextInput\nfrom django.utils.translation import ugettext_lazy as _  # type: ignore\n\nfrom nextcloudappstore.core.models import App, AppRating\n\nRATING_CHOICES = (\n    (0.0, _('Bad')),\n    (0.5, _('Ok')),\n    (1.0, _('Good'))\n)\n\n\nclass AppReleaseUploadForm(Form):\n    download = CharField(label=_('Download link (tar.gz)'), max_length=256,\n                         widget=TextInput(attrs={'required': 'required'}))\n    signature = CharField(widget=Textarea(attrs={'required': 'required'}),\n                          label=_('SHA512 signature'),\n                          help_text=_(\n                              'Can be generated by executing the '\n                              'following command: <b>openssl dgst -sha512 '\n                              '-sign ~/.nextcloud/certificates/APP_ID.key '\n                              '/path/to/app.tar.gz | openssl base64</b>'))\n    nightly = BooleanField(label=_('Nightly'), required=False)\n    safe_help_fields = ['signature']\n\n\nclass AppRegisterForm(Form):\n    certificate = CharField(\n        widget=Textarea(attrs={'required': 'required'}),\n        label=_('Public certificate'),\n        help_text=_(\n            'Usually stored in ~/.nextcloud/certificates/APP_ID.crt where '\n            'APP_ID is your app\\'s id. If you do not have a certificate you '\n            'need to create a certificate sign request (CSR) first which '\n            'should be posted on the <a '\n            'href=\"https://github.com/nextcloud/app-certificate-requests\" '\n            'rel=\"noreferrer noopener\">certificate repository</a> (follow '\n            'the README). You can generate the CSR by executing the '\n            'following command: <b>openssl req -nodes -newkey rsa:4096 '\n            '-keyout APP_ID.key -out APP_ID.csr -subj \"/CN=APP_ID\"</b>'))\n    signature = CharField(widget=Textarea(attrs={'required': 'required'}),\n                          label=_('SHA512 signature over your app\\'s id'),\n                          help_text=_(\n                              'Can be generated by executing the '\n                              'following '\n                              'command: <b>echo -n \"APP_ID\" | openssl dgst '\n                              '-sha512 -sign '\n                              '~/.nextcloud/certificates/APP_ID.key | '\n                              'openssl base64</b>'))\n    safe_help_fields = ['certificate', 'signature']\n\n\nclass AppRatingForm(Form):\n    def __init__(self, *args, **kwargs):\n        self._id = kwargs.pop('id', None)\n        self._user = kwargs.pop('user', None)\n        self._language_code = kwargs.pop('language_code', None)\n        super().__init__(*args, **kwargs)\n\n    rating = ChoiceField(initial=0.5, choices=RATING_CHOICES,\n                         widget=RadioSelect)\n    comment = CharField(widget=Textarea, required=False,\n                        label=_('Review'))\n\n    class Meta:\n        fields = ('rating', 'comment')\n\n    def save(self):\n        app = App.objects.get(id=self._id)\n        app_rating, created = AppRating.objects.get_or_create(user=self._user,\n                                                              app=app)\n        app_rating.rating = self.cleaned_data['rating']\n        app_rating.set_current_language(self._language_code)\n        app_rating.comment = self.cleaned_data['comment']\n        app_rating.save()\n", "path": "nextcloudappstore/core/forms.py"}, {"content": "from urllib.parse import urlencode\n\nfrom django.conf import settings\nfrom django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.contrib.auth.models import User\nfrom django.core.exceptions import ObjectDoesNotExist\nfrom django.db.models import Q\nfrom django.http import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import get_language, get_language_info\nfrom django.views.decorators.http import etag\nfrom django.views.generic import FormView\nfrom django.views.generic.base import TemplateView\nfrom django.views.generic.detail import DetailView\nfrom django.views.generic.list import ListView\nfrom rest_framework.generics import ListAPIView\nfrom semantic_version import Version\n\nfrom nextcloudappstore.core.api.v1.serializers import AppRatingSerializer\nfrom nextcloudappstore.core.caching import app_etag\nfrom nextcloudappstore.core.forms import AppRatingForm, AppReleaseUploadForm, \\\n    AppRegisterForm\nfrom nextcloudappstore.core.models import App, Category, AppRating\nfrom nextcloudappstore.core.scaffolding.archive import build_archive\nfrom nextcloudappstore.core.scaffolding.forms import AppScaffoldingForm\nfrom nextcloudappstore.core.versioning import pad_min_version\n\n\n@etag(app_etag)\ndef app_description(request, id):\n    app = get_object_or_404(App, id=id)\n    return HttpResponse(app.description, content_type='text/plain')\n\n\nclass AppRatingApi(ListAPIView):\n    serializer_class = AppRatingSerializer\n\n    def get_queryset(self):\n        id = self.kwargs.get('id')\n        app = get_object_or_404(App, id=id)\n        return AppRating.objects.language(self.request.LANGUAGE_CODE).filter(\n            app=app)\n\n\nclass LegalNoticeView(TemplateView):\n    template_name = 'legal.html'\n\n\nclass AppDetailView(DetailView):\n    queryset = App.objects.prefetch_related('releases', 'screenshots', 'owner',\n                                            'co_maintainers')\n    template_name = 'app/detail.html'\n    slug_field = 'id'\n    slug_url_kwarg = 'id'\n\n    def post(self, request, id):\n        form = AppRatingForm(request.POST, id=id, user=request.user,\n                             language_code=request.LANGUAGE_CODE)\n        # there is no way that a rating can be invalid by default\n        if form.is_valid() and request.user.is_authenticated:\n            form.save()\n        return redirect('app-detail', id=id)\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['rating_form'] = AppRatingForm()\n        context['user_has_rated_app'] = False\n        if self.request.user.is_authenticated:\n            try:\n                app_rating = AppRating.objects.get(user=self.request.user,\n                                                   app=context['app'])\n                # when accessing an empty comment django-parler tries to\n                # fall back to the default language. However for comments\n                # the default (English) does not always exist. Unfortunately\n                # it throws the same exception as non existing models,\n                # so we need to access it beforehand\n                try:\n                    comment = app_rating.comment\n                except AppRating.DoesNotExist:\n                    comment = ''\n\n                context['rating_form'] = AppRatingForm(initial={\n                    'rating': app_rating.rating,\n                    'comment': comment\n                })\n                context['user_has_rated_app'] = True\n            except AppRating.DoesNotExist:\n                pass\n        context['categories'] = Category.objects.prefetch_related(\n            'translations').all()\n        context['latest_releases_by_platform_v'] = \\\n            self.object.latest_releases_by_platform_v()\n        return context\n\n\nclass AppReleasesView(DetailView):\n    queryset = App.objects.prefetch_related(\n        'releases',\n        'releases__databases',\n        'releases__licenses',\n        'releases__phpextensiondependencies__php_extension',\n        'releases__databasedependencies__database',\n        'releases__shell_commands'\n    )\n    template_name = 'app/releases.html'\n    slug_field = 'id'\n    slug_url_kwarg = 'id'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['categories'] = Category.objects.prefetch_related(\n            'translations').all()\n\n        releases = self.object.releases_by_platform_v()\n        nightlies = self.object.nightly_releases_by_platform_v()\n        versions = set(list(releases.keys()) + list(nightlies.keys()))\n        all_releases = list(map(\n            lambda v: (v, releases.get(v, []) + nightlies.get(v, [])),\n            versions))\n        context['releases_by_platform_v'] = \\\n            self._sort_by_platform_v(all_releases)\n\n        return context\n\n    def _sort_by_platform_v(self, releases_by_platform, reverse=True):\n        \"\"\"Sorts a list of tuples like (<platform version>, [releases]) by\n        platform version.\n\n        :param releases_by_platform: A list of tuples.\n        :param reverse: Descending order if True, ascending otherwise.\n        :return sorted list of tuples.\n        \"\"\"\n\n        return sorted(releases_by_platform, reverse=reverse,\n                      key=lambda v: Version(pad_min_version(v[0])))\n\n\nclass CategoryAppListView(ListView):\n    model = App\n    template_name = 'app/list.html'\n    allow_empty = True\n\n    def get_queryset(self):\n        order_by = self.request.GET.get('order_by', 'rating_overall')\n        ordering = self.request.GET.get('ordering', 'desc')\n        featured = self.request.GET.get('featured', False)\n        maintainer = self.request.GET.get('maintainer', False)\n        sort_columns = []\n\n        allowed_order_by = {'name', 'last_release', 'rating_overall',\n                            'rating_recent'}\n        if order_by in allowed_order_by:\n            if order_by == 'name':\n                order_by = 'translations__name'\n            if ordering == 'desc':\n                sort_columns.append('-' + order_by)\n            else:\n                sort_columns.append(order_by)\n\n        lang = get_language_info(get_language())['code']\n        category_id = self.kwargs['id']\n        queryset = App.objects.search(self.search_terms, lang).order_by(\n            *sort_columns).filter(releases__gt=0)\n        if maintainer:\n            try:\n                user = User.objects.get_by_natural_key(maintainer)\n                queryset = queryset.filter(Q(owner=user) |\n                                           Q(co_maintainers=user))\n            except ObjectDoesNotExist:\n                return queryset.none()\n        if category_id:\n            queryset = queryset.filter(categories__id=category_id)\n        if featured == \"true\":\n            queryset = queryset.filter(featured=True)\n        return queryset.prefetch_related('screenshots', 'translations')\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['categories'] = Category.objects.prefetch_related(\n            'translations').all()\n        category_id = self.kwargs['id']\n        if category_id:\n            context['current_category'] = Category.objects.get(id=category_id)\n        if self.search_terms:\n            context['search_query'] = ' '.join(self.search_terms)\n        context['url_params'] = self.url_params\n        return context\n\n    @cached_property\n    def url_params(self):\n        \"\"\"URL encoded strings with the GET params of the last request.\n\n        Intended for preserving GET params upon clicking a link by including\n        one (and only one) of these strings in the \"href\" attribute.\n\n        The parameters are divided into three groups: search, filters and\n        ordering. In addition to these three, the returned dict also contains\n        some combinations of them, as specified by the dict keys.\n\n        No leading \"?\" or \"&\".\n\n        :return dict with URL encoded strings.\n        \"\"\"\n\n        search = self._url_params_str('search')\n        filters = self._url_params_str('featured', 'maintainer')\n        ordering = self._url_params_str('order_by', 'ordering')\n\n        return {\n            'search': search,\n            'filters': filters,\n            'ordering': ordering,\n            'search_filters': self._join_url_params_strs(search, filters),\n            'filters_ordering': self._join_url_params_strs(filters, ordering),\n        }\n\n    def _url_params_str(self, *params):\n        args = map(lambda param: (param, self.request.GET.get(param, '')),\n                   params)\n        present_args = filter(lambda a: a[1], args)\n        return urlencode(dict(present_args))\n\n    def _join_url_params_strs(self, *strings):\n        return '&'.join(filter(None, strings))\n\n    @cached_property\n    def search_terms(self):\n        return self.request.GET.get('search', '').strip().split()\n\n\nclass AppUploadView(LoginRequiredMixin, TemplateView):\n    template_name = 'app/upload.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['form'] = AppReleaseUploadForm()\n        return context\n\n\nclass AppScaffoldingView(FormView):\n    template_name = 'app/scaffold.html'\n    form_class = AppScaffoldingForm\n\n    def get_initial(self):\n        init = {\n            'platform': settings.CURRENT_PLATFORM_STABLE_VERSION,\n            'categories': ('tools',)\n        }\n        if self.request.user.is_authenticated:\n            user = self.request.user\n            init['author_name'] = '%s %s' % (user.first_name, user.last_name)\n            init['author_email'] = user.email\n        return init\n\n    def form_valid(self, form):\n        buffer = build_archive(form.cleaned_data)\n        response = HttpResponse(content_type='application/tar+gzip')\n        response['Content-Disposition'] = 'attachment; filename=\"app.tar.gz\"'\n        value = buffer.getvalue()\n        buffer.close()\n        response.write(value)\n        return response\n\n\nclass AppRegisterView(LoginRequiredMixin, TemplateView):\n    template_name = 'app/register.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['form'] = AppRegisterForm()\n        return context\n", "path": "nextcloudappstore/core/views.py"}], "after_files": [{"content": "from django.forms import Form, CharField, Textarea, ChoiceField, RadioSelect, \\\n    BooleanField, TextInput\nfrom django.utils.translation import ugettext_lazy as _  # type: ignore\n\nfrom nextcloudappstore.core.models import App, AppRating\n\nRATING_CHOICES = (\n    (0.0, _('Bad')),\n    (0.5, _('Ok')),\n    (1.0, _('Good'))\n)\n\n\nclass AppReleaseUploadForm(Form):\n    download = CharField(label=_('Download link (tar.gz)'), max_length=256,\n                         widget=TextInput(attrs={'required': 'required'}))\n    signature = CharField(widget=Textarea(attrs={'required': 'required'}),\n                          label=_('SHA512 signature'),\n                          help_text=_(\n                              'Can be generated by executing the '\n                              'following command: <b>openssl dgst -sha512 '\n                              '-sign ~/.nextcloud/certificates/APP_ID.key '\n                              '/path/to/app.tar.gz | openssl base64</b>'))\n    nightly = BooleanField(label=_('Nightly'), required=False)\n    safe_help_fields = ['signature']\n\n\nclass AppRegisterForm(Form):\n    certificate = CharField(\n        widget=Textarea(attrs={'required': 'required'}),\n        label=_('Public certificate'),\n        help_text=_(\n            'Usually stored in ~/.nextcloud/certificates/APP_ID.crt where '\n            'APP_ID is your app\\'s id. If you do not have a certificate you '\n            'need to create a certificate sign request (CSR) first which '\n            'should be posted on the <a '\n            'href=\"https://github.com/nextcloud/app-certificate-requests\" '\n            'rel=\"noreferrer noopener\">certificate repository</a> (follow '\n            'the README). You can generate the CSR by executing the '\n            'following command: <b>openssl req -nodes -newkey rsa:4096 '\n            '-keyout APP_ID.key -out APP_ID.csr -subj \"/CN=APP_ID\"</b>'))\n    signature = CharField(widget=Textarea(attrs={'required': 'required'}),\n                          label=_('SHA512 signature over your app\\'s id'),\n                          help_text=_(\n                              'Can be generated by executing the '\n                              'following '\n                              'command: <b>echo -n \"APP_ID\" | openssl dgst '\n                              '-sha512 -sign '\n                              '~/.nextcloud/certificates/APP_ID.key | '\n                              'openssl base64</b>'))\n    safe_help_fields = ['certificate', 'signature']\n\n\nclass AppRatingForm(Form):\n    def __init__(self, *args, **kwargs):\n        self._id = kwargs.pop('id', None)\n        self._user = kwargs.pop('user', None)\n        self._language_code = kwargs.pop('language_code', None)\n        super().__init__(*args, **kwargs)\n\n    rating = ChoiceField(initial=0.5, choices=RATING_CHOICES,\n                         widget=RadioSelect)\n    comment = CharField(widget=Textarea, required=False,\n                        label=_('Comment'))\n\n    class Meta:\n        fields = ('rating', 'comment')\n\n    def save(self):\n        app = App.objects.get(id=self._id)\n        app_rating, created = AppRating.objects.get_or_create(user=self._user,\n                                                              app=app)\n        app_rating.rating = self.cleaned_data['rating']\n        app_rating.set_current_language(self._language_code)\n        app_rating.comment = self.cleaned_data['comment']\n        app_rating.save()\n", "path": "nextcloudappstore/core/forms.py"}, {"content": "from urllib.parse import urlencode\n\nfrom django.conf import settings\nfrom django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.contrib.auth.models import User\nfrom django.core.exceptions import ObjectDoesNotExist\nfrom django.db.models import Q\nfrom django.http import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import get_language, get_language_info\nfrom django.views.decorators.http import etag\nfrom django.views.generic import FormView\nfrom django.views.generic.base import TemplateView\nfrom django.views.generic.detail import DetailView\nfrom django.views.generic.list import ListView\nfrom rest_framework.generics import ListAPIView\nfrom semantic_version import Version\n\nfrom nextcloudappstore.core.api.v1.serializers import AppRatingSerializer\nfrom nextcloudappstore.core.caching import app_etag\nfrom nextcloudappstore.core.forms import AppRatingForm, AppReleaseUploadForm, \\\n    AppRegisterForm\nfrom nextcloudappstore.core.models import App, Category, AppRating\nfrom nextcloudappstore.core.scaffolding.archive import build_archive\nfrom nextcloudappstore.core.scaffolding.forms import AppScaffoldingForm\nfrom nextcloudappstore.core.versioning import pad_min_version\n\n\n@etag(app_etag)\ndef app_description(request, id):\n    app = get_object_or_404(App, id=id)\n    return HttpResponse(app.description, content_type='text/plain')\n\n\nclass AppRatingApi(ListAPIView):\n    serializer_class = AppRatingSerializer\n\n    def get_queryset(self):\n        id = self.kwargs.get('id')\n        app = get_object_or_404(App, id=id)\n        return AppRating.objects.language(self.request.LANGUAGE_CODE).filter(\n            app=app)\n\n\nclass LegalNoticeView(TemplateView):\n    template_name = 'legal.html'\n\n\nclass AppDetailView(DetailView):\n    queryset = App.objects.prefetch_related('releases', 'screenshots', 'owner',\n                                            'co_maintainers')\n    template_name = 'app/detail.html'\n    slug_field = 'id'\n    slug_url_kwarg = 'id'\n\n    def post(self, request, id):\n        form = AppRatingForm(request.POST, id=id, user=request.user,\n                             language_code=request.LANGUAGE_CODE)\n        # there is no way that a rating can be invalid by default\n        if form.is_valid() and request.user.is_authenticated:\n            form.save()\n        return redirect('app-detail', id=id)\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['rating_form'] = AppRatingForm()\n        context['user_has_rated_app'] = False\n        if self.request.user.is_authenticated:\n            try:\n                app_rating = AppRating.objects.get(user=self.request.user,\n                                                   app=context['app'])\n                # when accessing an empty comment django-parler tries to\n                # fall back to the default language. However for comments\n                # the default (English) does not always exist. Unfortunately\n                # it throws the same exception as non existing models,\n                # so we need to access it beforehand\n                try:\n                    comment = app_rating.comment\n                except AppRating.DoesNotExist:\n                    comment = ''\n\n                context['rating_form'] = AppRatingForm({\n                    'rating': app_rating.rating,\n                    'comment': comment\n                })\n                context['user_has_rated_app'] = True\n            except AppRating.DoesNotExist:\n                pass\n        context['categories'] = Category.objects.prefetch_related(\n            'translations').all()\n        context['latest_releases_by_platform_v'] = \\\n            self.object.latest_releases_by_platform_v()\n        return context\n\n\nclass AppReleasesView(DetailView):\n    queryset = App.objects.prefetch_related(\n        'releases',\n        'releases__databases',\n        'releases__licenses',\n        'releases__phpextensiondependencies__php_extension',\n        'releases__databasedependencies__database',\n        'releases__shell_commands'\n    )\n    template_name = 'app/releases.html'\n    slug_field = 'id'\n    slug_url_kwarg = 'id'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['categories'] = Category.objects.prefetch_related(\n            'translations').all()\n\n        releases = self.object.releases_by_platform_v()\n        nightlies = self.object.nightly_releases_by_platform_v()\n        versions = set(list(releases.keys()) + list(nightlies.keys()))\n        all_releases = list(map(\n            lambda v: (v, releases.get(v, []) + nightlies.get(v, [])),\n            versions))\n        context['releases_by_platform_v'] = \\\n            self._sort_by_platform_v(all_releases)\n\n        return context\n\n    def _sort_by_platform_v(self, releases_by_platform, reverse=True):\n        \"\"\"Sorts a list of tuples like (<platform version>, [releases]) by\n        platform version.\n\n        :param releases_by_platform: A list of tuples.\n        :param reverse: Descending order if True, ascending otherwise.\n        :return sorted list of tuples.\n        \"\"\"\n\n        return sorted(releases_by_platform, reverse=reverse,\n                      key=lambda v: Version(pad_min_version(v[0])))\n\n\nclass CategoryAppListView(ListView):\n    model = App\n    template_name = 'app/list.html'\n    allow_empty = True\n\n    def get_queryset(self):\n        order_by = self.request.GET.get('order_by', 'rating_overall')\n        ordering = self.request.GET.get('ordering', 'desc')\n        featured = self.request.GET.get('featured', False)\n        maintainer = self.request.GET.get('maintainer', False)\n        sort_columns = []\n\n        allowed_order_by = {'name', 'last_release', 'rating_overall',\n                            'rating_recent'}\n        if order_by in allowed_order_by:\n            if order_by == 'name':\n                order_by = 'translations__name'\n            if ordering == 'desc':\n                sort_columns.append('-' + order_by)\n            else:\n                sort_columns.append(order_by)\n\n        lang = get_language_info(get_language())['code']\n        category_id = self.kwargs['id']\n        queryset = App.objects.search(self.search_terms, lang).order_by(\n            *sort_columns).filter(releases__gt=0)\n        if maintainer:\n            try:\n                user = User.objects.get_by_natural_key(maintainer)\n                queryset = queryset.filter(Q(owner=user) |\n                                           Q(co_maintainers=user))\n            except ObjectDoesNotExist:\n                return queryset.none()\n        if category_id:\n            queryset = queryset.filter(categories__id=category_id)\n        if featured == \"true\":\n            queryset = queryset.filter(featured=True)\n        return queryset.prefetch_related('screenshots', 'translations')\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['categories'] = Category.objects.prefetch_related(\n            'translations').all()\n        category_id = self.kwargs['id']\n        if category_id:\n            context['current_category'] = Category.objects.get(id=category_id)\n        if self.search_terms:\n            context['search_query'] = ' '.join(self.search_terms)\n        context['url_params'] = self.url_params\n        return context\n\n    @cached_property\n    def url_params(self):\n        \"\"\"URL encoded strings with the GET params of the last request.\n\n        Intended for preserving GET params upon clicking a link by including\n        one (and only one) of these strings in the \"href\" attribute.\n\n        The parameters are divided into three groups: search, filters and\n        ordering. In addition to these three, the returned dict also contains\n        some combinations of them, as specified by the dict keys.\n\n        No leading \"?\" or \"&\".\n\n        :return dict with URL encoded strings.\n        \"\"\"\n\n        search = self._url_params_str('search')\n        filters = self._url_params_str('featured', 'maintainer')\n        ordering = self._url_params_str('order_by', 'ordering')\n\n        return {\n            'search': search,\n            'filters': filters,\n            'ordering': ordering,\n            'search_filters': self._join_url_params_strs(search, filters),\n            'filters_ordering': self._join_url_params_strs(filters, ordering),\n        }\n\n    def _url_params_str(self, *params):\n        args = map(lambda param: (param, self.request.GET.get(param, '')),\n                   params)\n        present_args = filter(lambda a: a[1], args)\n        return urlencode(dict(present_args))\n\n    def _join_url_params_strs(self, *strings):\n        return '&'.join(filter(None, strings))\n\n    @cached_property\n    def search_terms(self):\n        return self.request.GET.get('search', '').strip().split()\n\n\nclass AppUploadView(LoginRequiredMixin, TemplateView):\n    template_name = 'app/upload.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['form'] = AppReleaseUploadForm()\n        return context\n\n\nclass AppScaffoldingView(FormView):\n    template_name = 'app/scaffold.html'\n    form_class = AppScaffoldingForm\n\n    def get_initial(self):\n        init = {\n            'platform': settings.CURRENT_PLATFORM_STABLE_VERSION,\n            'categories': ('tools',)\n        }\n        if self.request.user.is_authenticated:\n            user = self.request.user\n            init['author_name'] = '%s %s' % (user.first_name, user.last_name)\n            init['author_email'] = user.email\n        return init\n\n    def form_valid(self, form):\n        buffer = build_archive(form.cleaned_data)\n        response = HttpResponse(content_type='application/tar+gzip')\n        response['Content-Disposition'] = 'attachment; filename=\"app.tar.gz\"'\n        value = buffer.getvalue()\n        buffer.close()\n        response.write(value)\n        return response\n\n\nclass AppRegisterView(LoginRequiredMixin, TemplateView):\n    template_name = 'app/register.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['form'] = AppRegisterForm()\n        return context\n", "path": "nextcloudappstore/core/views.py"}]}