internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: digitalfabrik/integreat-cms

Issue:
Region list menu points to api
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
The menu item for regions points to the region api and not the region list.

### Steps to Reproduce

1. Go to 'Regions'

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The region list (`/regions/`) opens.

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The region api (`/api/regions/`) opens.

### Additional Information
<!-- Add any other context (e.g. logs, screenshots, etc.) about the problem here. -->
This is because both urls have the name 'regions' and the last matching item in urlpatterns determines the actual url.

Region list menu points to api
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
The menu item for regions points to the region api and not the region list.

### Steps to Reproduce

1. Go to 'Regions'

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The region list (`/regions/`) opens.

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The region api (`/api/regions/`) opens.

### Additional Information
<!-- Add any other context (e.g. logs, screenshots, etc.) about the problem here. -->
This is because both urls have the name 'regions' and the last matching item in urlpatterns determines the actual url.



Discussion:

Resolving patch:
diff --git a/src/api/urls.py b/src/api/urls.py
--- a/src/api/urls.py
+++ b/src/api/urls.py
@@ -17,10 +17,10 @@
 from .v3.single_page import single_page
 
 urlpatterns = [
-    url(r'regions/$', regions, name='regions'),
-    url(r'regions/live/$', liveregions, name='liveregions'),
-    url(r'regions/hidden/$', hiddenregions, name='hiddenregions'),
-    url(r'regions/pushnew/$', pushnew, name='pushnew'),
+    url(r'regions/$', regions),
+    url(r'regions/live/$', liveregions),
+    url(r'regions/hidden/$', hiddenregions),
+    url(r'regions/pushnew/$', pushnew),
     url(r'(?P<region_slug>[-\w]+)/', include([
         url(r'languages/$', languages),
         url(r'offers/$', offers),


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
Write suceessful/failed logins to syslog
https://docs.python.org/3/library/logging.handlers.html#sysloghandler

This should probably be priority NOTICE and facility LOG_AUTH.


Discussion:

Resolving patch:
diff --git a/src/backend/settings.py b/src/backend/settings.py
--- a/src/backend/settings.py
+++ b/src/backend/settings.py
@@ -184,9 +184,33 @@
 LOGGING = {
     'version': 1,
     'disable_existing_loggers': False,
+    'formatters': {
+        'default': {
+            'format': 'INTEGREAT CMS - %(levelname)s: %(message)s',
+        },
+        'console': {
+            'format': '%(asctime)s INTEGREAT CMS - %(levelname)s: %(message)s',
+            'datefmt': '%b %d %H:%M:%S',
+        }
+    },
     'handlers': {
         'console': {
-            'class': 'logging.StreamHandler'
+            'class': 'logging.StreamHandler',
+            'formatter': 'console'
+        },
+        'authlog': {
+            'level': 'INFO',
+            'class': 'logging.handlers.SysLogHandler',
+            'address': '/dev/log',
+            'facility': 'auth',
+            'formatter': 'default',
+        },
+        'syslog': {
+            'level': 'INFO',
+            'class': 'logging.handlers.SysLogHandler',
+            'address': '/dev/log',
+            'facility': 'syslog',
+            'formatter': 'default',
         },
     },
     'loggers': {
@@ -210,6 +234,10 @@
             'level': 'DEBUG',
             'propagate': True,
         },
+        'auth': {
+            'handlers': ['console', 'authlog', 'syslog'],
+            'level': 'INFO',
+        },
     }
 }
 
diff --git a/src/cms/apps.py b/src/cms/apps.py
--- a/src/cms/apps.py
+++ b/src/cms/apps.py
@@ -1,7 +1,10 @@
 import logging
 import sys
+
 from django.conf import settings
 from django.apps import AppConfig
+from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
+from django.dispatch import receiver
 
 logger = logging.getLogger(__name__)
 
@@ -27,3 +30,21 @@ def ready(self):
         if settings.SECRET_KEY == '-!v282$zj815_q@htaxcubylo)(l%a+k*-xi78hw*#s2@i86@_' and not settings.DEBUG:
             logger.error("You are running the Integreat CMS in production mode. Change the SECRET_KEY in the settings.py!")
             sys.exit(1)
+
+
+authlog = logging.getLogger("auth")
+
+@receiver(user_logged_in)
+def user_logged_in_callback(sender, request, user, **kwargs):  # pylint: disable=unused-argument
+    ip = request.META.get('REMOTE_ADDR')
+    authlog.info('login user=%s, ip=%s', user, ip)
+
+@receiver(user_logged_out)
+def user_logged_out_callback(sender, request, user, **kwargs):  # pylint: disable=unused-argument
+    ip = request.META.get('REMOTE_ADDR')
+    authlog.info('logout user=%s, ip=%s', user, ip)
+
+@receiver(user_login_failed)
+def user_login_failed_callback(sender, credentials, request, **kwargs):  # pylint: disable=unused-argument
+    ip = request.META.get('REMOTE_ADDR')
+    authlog.warning('login failed user=%s, ip=%s', credentials['username'], ip)


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
FieldError when accessing event
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
When opening the editor page for an event, a `FieldError` occurs.


### Steps to Reproduce

1. Go to 'Events'
2. Click on an event or on the 'Create event' button
3. Error occurs (see screenshot below)

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
Event editor page opens up


### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
Error page is loaded 


### Additional Information
<!-- Add any other context (e.g. logs, screenshots, etc.) about the problem here. -->
![Screenshot_20200731_154413](https://user-images.githubusercontent.com/40687216/89044629-8162d500-d34a-11ea-9477-3e64e411827f.png)





Discussion:

Resolving patch:
diff --git a/src/cms/views/events/event_view.py b/src/cms/views/events/event_view.py
--- a/src/cms/views/events/event_view.py
+++ b/src/cms/views/events/event_view.py
@@ -37,7 +37,7 @@ def get(self, request, *args, **kwargs):
         recurrence_rule_instance = RecurrenceRule.objects.filter(
             event=event_instance
         ).first()
-        poi_instance = POI.objects.filter(event=event_instance).first()
+        poi_instance = POI.objects.filter(events=event_instance).first()
 
         # Make form disabled if user has no permission to edit the page
         if not request.user.has_perm("cms.edit_events"):


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
Do not commit trivial changes to documentation
### Motivation
<!-- A clear and concise description of what the motivation for the new feature is, and what problem it is solving. -->
At the moment, our CircleCI jobs `build-documentation` and `deploy-documentation` automatically build our documentation and commit/push it to the `gh-pages` branch. Most of the times, this commit includes only trivial changes (see e.g. 6d6c89beda44ebd2448526a18636c464e1111355). This makes the "last changed" date very unreliable, because it is always the date of the last commit, not the date when the documentation actually changed the last time.

### Proposed Solution
<!-- A clear and concise description of the feature you would like to add, and how it solves the motivating problem. -->
Do not commit the changes to the documentation if only the "Last updated on ..." changes

### Alternatives
<!-- A clear and concise description of any alternative solutions or features you've considered, and why you're proposed solution is better. -->
Remove the "last changed" date

Do not commit trivial changes to documentation
### Motivation
<!-- A clear and concise description of what the motivation for the new feature is, and what problem it is solving. -->
At the moment, our CircleCI jobs `build-documentation` and `deploy-documentation` automatically build our documentation and commit/push it to the `gh-pages` branch. Most of the times, this commit includes only trivial changes (see e.g. 6d6c89beda44ebd2448526a18636c464e1111355). This makes the "last changed" date very unreliable, because it is always the date of the last commit, not the date when the documentation actually changed the last time.

### Proposed Solution
<!-- A clear and concise description of the feature you would like to add, and how it solves the motivating problem. -->
Do not commit the changes to the documentation if only the "Last updated on ..." changes

### Alternatives
<!-- A clear and concise description of any alternative solutions or features you've considered, and why you're proposed solution is better. -->
Remove the "last changed" date



Discussion:

Resolving patch:
diff --git a/sphinx/conf.py b/sphinx/conf.py
--- a/sphinx/conf.py
+++ b/sphinx/conf.py
@@ -56,6 +56,7 @@ def setup(app):
     "sphinx.ext.linkcode",
     "sphinxcontrib_django",
     "sphinx_rtd_theme",
+    "sphinx_last_updated_by_git",
 ]
 
 # Enable cross-references to other documentations


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
Embedding live content not working
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
At the moment, embedding live content in pages is not working.

### Steps to Reproduce

1. Go to a region, e.g. "Augsburg"
2. Click on a page, e.g. "Welcome"
3. In the dropdown "Embed live content" select another  region, e.g. "Nürnberg"
4. Nothing happens

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The next dropdown with the page selection should appear

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
Nothing appears
### Additional Information
<!-- Add any other context (e.g. logs, screenshots, etc.) about the problem here. -->
The console and the network analysis tab reveal the traceback:

```
FieldError at /ajax/get_pages_list

Cannot resolve keyword 'title' into field.

/home/timo/job/integreat/django/src/cms/views/pages/page_actions.py in get_pages_list_ajax

432.    pages = Page.objects.filter(region__id=region_id).order_by("title")
```

So the problem is very straight forward: the `Page` model does not have a `title` attribute, thus we cannot sort by the title.


Discussion:

Resolving patch:
diff --git a/src/cms/views/pages/page_actions.py b/src/cms/views/pages/page_actions.py
--- a/src/cms/views/pages/page_actions.py
+++ b/src/cms/views/pages/page_actions.py
@@ -509,7 +509,7 @@ def get_pages_list_ajax(request):
         page.save()
         return JsonResponse({"nolist": True})
     region_id = decoded_json["region"]
-    pages = Page.objects.filter(region__id=region_id).order_by("title")
+    pages = Page.objects.filter(region__id=region_id)
     result = []
     for page in pages:
         result.append(
@@ -523,6 +523,7 @@ def get_pages_list_ajax(request):
                 ),
             }
         )
+    result = sorted(result, key=lambda k: k["name"])
     return JsonResponse(result, safe=False)
 
 


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
Pages endpoint: skip pages if parent is not visible
If a parent page in the page tree is in any state that makes it invisible in the API, we do not want the children to appear in the pages endpoint. This should allow for easy deactivating of "full chapters". 
Pages endpoint: skip pages if parent is not visible
If a parent page in the page tree is in any state that makes it invisible in the API, we do not want the children to appear in the pages endpoint. This should allow for easy deactivating of "full chapters". 


Discussion:
Just to wrap my head around this... this does only apply to the `archived` flag, not to the `draft`/`review`/`public`-status of the page translations, right?
I thought that, when a page is set as draft or in-review, the API should deliver the most recent public revision instead... and only when a page is archived, it is completely deactivated in the API... right?
Yes, in most cases this only applies to `archived`. But if there is no released version of the parent, i.e. there is only the current `draft` version, then children should not be shown as well.

So we need to check if there is any version of the PageTranslation that can be delivered via API. And if there is none, then we need to exclude the children.
Just to wrap my head around this... this does only apply to the `archived` flag, not to the `draft`/`review`/`public`-status of the page translations, right?
I thought that, when a page is set as draft or in-review, the API should deliver the most recent public revision instead... and only when a page is archived, it is completely deactivated in the API... right?
Yes, in most cases this only applies to `archived`. But if there is no released version of the parent, i.e. there is only the current `draft` version, then children should not be shown as well.

So we need to check if there is any version of the PageTranslation that can be delivered via API. And if there is none, then we need to exclude the children.

Resolving patch:
diff --git a/src/api/v3/pages.py b/src/api/v3/pages.py
--- a/src/api/v3/pages.py
+++ b/src/api/v3/pages.py
@@ -36,10 +36,20 @@ def transform_page(page_translation):
 def pages(request, region_slug, language_code):
     region = Region.get_current_region(request)
     result = []
-    for page in region.pages.all():
+    for page in region.pages.filter(archived=False, parent=None):  # get main level
         page_translation = page.get_public_translation(language_code)
         if page_translation:
             result.append(transform_page(page_translation))
+            result = get_children(page, language_code, result)
     return JsonResponse(
         result, safe=False
     )  # Turn off Safe-Mode to allow serializing arrays
+
+
+def get_children(parent, language_code, result):
+    for page in parent.children.filter(archived=False):
+        page_translation = page.get_public_translation(language_code)
+        if page_translation:
+            result.append(transform_page(page_translation))
+            result = get_children(page, language_code, result)
+    return result


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
Old permalinks not mapped in single page API endpoint
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
The permalink is checked for correctness in the single page API endpoint, but in #119 we decided not to keep track of old permalinks. Instead, we will just map permalinks based on the last url parameter (the slug) and ignore the rest.

### Steps to Reproduce

1. Copy one page permalink
2. Move that page to another parent to change the permalink
3. Request this page in the single page API endpoint with the old permalink from step 1

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The page should be found even if the permalink is old

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The error `No Page matches the given url or id` is returned.





Discussion:

Resolving patch:
diff --git a/src/api/v3/single_page.py b/src/api/v3/single_page.py
--- a/src/api/v3/single_page.py
+++ b/src/api/v3/single_page.py
@@ -5,7 +5,7 @@
 from django.http import JsonResponse, Http404
 from django.shortcuts import get_object_or_404
 
-from cms.models import Region, Page
+from cms.models import Region
 from .pages import transform_page
 
 
@@ -40,15 +40,17 @@ def single_page(request, region_slug, language_code):
     elif request.GET.get("url"):
         # Strip leading and trailing slashes to avoid ambiguous urls
         url = request.GET.get("url").strip("/")
-        # Get potential page candidate by only filtering for the translation slug
+        # The last path component of the url is the page translation slug
+        page_translation_slug = url.split("/")[-1]
+        # Get page by filtering for translation slug and translation language code
         page = get_object_or_404(
-            Page, region=region, translations__slug=url.split("/")[-1]
+            region.pages,
+            translations__slug=page_translation_slug,
+            translations__language__code=language_code,
         )
         # Get most recent public revision of the page
         page_translation = page.get_public_translation(language_code)
-        # Check if the whole path is correct, not only the slug
-        # TODO: Once we have a permalink mapping of old versions, we also have to check whether the permalink was valid in the past
-        if page_translation.permalink == url:
+        if page_translation:
             return JsonResponse(transform_page(page_translation), safe=False)
 
     raise Http404("No Page matches the given url or id.")


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
Show latest feedback in dashboard
Show admins and content creators the latest feedback from app users in dashboard. This should be a list of the last ~5 messages. In some cases, the feedback only contains a thumbs up or down, in other cases it can contain a message. The title of the page or event concerned should be displayed as well and linked to the editing page.

Additional option: Add link that sends the message string to translate.google.com or deepl.com for translation. This can be useful if the feedback is given in a language the back end user does not understand. It is perfectly fine, if the link opens the translation website in a new tab. No need to fetch a translation via the API.


Discussion:

Resolving patch:
diff --git a/src/cms/views/dashboard/admin_dashboard_view.py b/src/cms/views/dashboard/admin_dashboard_view.py
--- a/src/cms/views/dashboard/admin_dashboard_view.py
+++ b/src/cms/views/dashboard/admin_dashboard_view.py
@@ -4,6 +4,7 @@
 from django.views.generic import TemplateView
 
 from ...decorators import staff_required
+from ...models import Feedback
 
 
 @method_decorator(login_required, name="dispatch")
@@ -34,6 +35,14 @@ def get(self, request, *args, **kwargs):
         :return: The rendered template response
         :rtype: ~django.template.response.TemplateResponse
         """
-
-        val = "To be defined"
-        return render(request, self.template_name, {"key": val, **self.base_context})
+        all_feedback = Feedback.objects.filter(is_technical=True)[:5]
+
+        return render(
+            request,
+            self.template_name,
+            {
+                "current_menu_item": "admin_feedback",
+                "all_feedback": all_feedback,
+                **self.base_context,
+            },
+        )
diff --git a/src/cms/views/dashboard/dashboard_view.py b/src/cms/views/dashboard/dashboard_view.py
--- a/src/cms/views/dashboard/dashboard_view.py
+++ b/src/cms/views/dashboard/dashboard_view.py
@@ -41,7 +41,6 @@ def get(self, request, *args, **kwargs):
         :rtype: ~django.template.response.TemplateResponse
         """
 
-        val = "To be defined"
         language_code = translation.get_language()
         feed = feedparser.parse(RSS_FEED_URLS[language_code])
         # select five most recent feeds
@@ -54,7 +53,6 @@ def get(self, request, *args, **kwargs):
             request,
             self.template_name,
             {
-                "key": val,
                 **self.base_context,
                 "feed": feed,
                 "home_page": RSS_FEED_URLS["home-page"],


Test patch:
Repository: digitalfabrik/integreat-cms

Issue:
get_last_root_page template tag not working
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
The `get_last_root_page` template tag is not working:
https://github.com/Integreat/integreat-cms/blob/develop/src/cms/templatetags/page_filters.py#L10-L20

This is because in the page QuerySet aggregation, the difference() function is used:
https://github.com/Integreat/integreat-cms/blob/a285cb3c74b2a2c501147076338e2b2a70c89bd6/src/cms/models/regions/region.py#L177

After difference(), it is not possible to use filter(), see https://docs.djangoproject.com/en/2.2/ref/models/querysets/#union

This leads to the last drop-region in the page tree being incorrectly tied to the last page in the list, not necessarily the last root page.

### Steps to Reproduce

1. Go to Page tree
2. Drag & drop page to most bottom line

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The page should be placed next to the last root page

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The page is placed next to the last page in the list

### Additional Information
<!-- Add any other context (e.g. logs, screenshots, etc.) about the problem here. -->




Discussion:

Resolving patch:
diff --git a/src/cms/templatetags/page_filters.py b/src/cms/templatetags/page_filters.py
--- a/src/cms/templatetags/page_filters.py
+++ b/src/cms/templatetags/page_filters.py
@@ -12,9 +12,9 @@ def get_last_root_page(pages):
     This tag returns the last page on the root level.
 
     :param pages: The requested page tree
-    :type pages: ~mptt.querysets.TreeQuerySet [ ~cms.models.pages.page.Page ]
+    :type pages: list [ ~cms.models.pages.page.Page ]
 
-    :return: The last root page of the given :class:`~django.db.models.query.QuerySet`
+    :return: The last root page of the given page list
     :rtype: ~cms.models.pages.page.Page
     """
-    return pages.filter(parent=None).last()
+    return list(filter(lambda p: not p.parent, pages))[-1]


Test patch: