internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: akvo/akvo-rsr

Issue:
Allows actions on self in User management
For superusers, RSR admins and organisation admins, it should be possible to do actions on their own user account in User management.



Discussion:

Resolving patch:
diff --git a/akvo/rest/views/user_management.py b/akvo/rest/views/user_management.py
--- a/akvo/rest/views/user_management.py
+++ b/akvo/rest/views/user_management.py
@@ -54,17 +54,27 @@ def valid_email(email_address):
     else:
         data = json.loads(data)
 
-    # Check email
-    email = data['email'].lower().strip()
-    if not (email and valid_email(email) and user.email != email):
-        missing_data.append('email')
-
     # Check organisation
     try:
         organisation = Organisation.objects.get(pk=int(data['organisation']))
     except (Organisation.DoesNotExist, ValueError):
         missing_data.append('organisation')
 
+    # Check email
+    email = data['email'].lower().strip()
+    if not (email and valid_email(email)):
+        missing_data.append('email')
+    elif user.email == email and organisation:
+        # Only superusers, RSR admins and organisation admins can invite themselves
+        if not (user.is_admin or user.is_superuser):
+            admin_group = Group.objects.get(name='Admins')
+            content_owned = []
+            for empl in Employment.objects.filter(user=user, group=admin_group).exclude(
+                    organisation=None):
+                content_owned += empl.organisation.content_owned_organisations()
+            if organisation not in content_owned:
+                missing_data.append('email')
+
     # Check group
     try:
         group = Group.objects.get(pk=int(data['group']))
diff --git a/akvo/rsr/views/my_rsr.py b/akvo/rsr/views/my_rsr.py
--- a/akvo/rsr/views/my_rsr.py
+++ b/akvo/rsr/views/my_rsr.py
@@ -428,11 +428,12 @@ def user_management(request):
         ]
         organisations = Organisation.objects.filter(pk__in=connected_orgs_list).\
             content_owned_organisations()
-        employments = organisations.employments().exclude(user=user).order_by('-id')
         if org_admin:
             roles = Group.objects.filter(name__in=groups)
+            employments = organisations.employments().order_by('-id')
         else:
             roles = Group.objects.filter(name__in=groups[:-1])
+            employments = organisations.employments().exclude(user=user).order_by('-id')
 
     q = request.GET.get('q')
     if q:


Test patch:
Repository: akvo/akvo-rsr

Issue:
Allow Admins to do the same as M&E Managers
In the results framework, M&E Managers can now perform specific actions that Admins can not (unlock periods, approve updates, etc). 

An Admin should be able to do at least the same as an M&E Manager.



Discussion:

Resolving patch:
diff --git a/akvo/rsr/views/my_rsr.py b/akvo/rsr/views/my_rsr.py
--- a/akvo/rsr/views/my_rsr.py
+++ b/akvo/rsr/views/my_rsr.py
@@ -547,7 +547,9 @@ def my_results(request, project_id):
         raise PermissionDenied
 
     me_managers_group = Group.objects.get(name='M&E Managers')
-    me_managers = project.publishing_orgs.employments().approved().filter(group=me_managers_group)
+    admins_group = Group.objects.get(name='Admins')
+    me_managers = project.publishing_orgs.employments().approved().\
+        filter(group__in=[admins_group, me_managers_group])
 
     context = {
         'project': project,


Test patch:
Repository: akvo/akvo-rsr

Issue:
Bug in get_admin_employment_orgs()
The `get_admin_employment_orgs` has a bug throwing a `TypeError` in certain cases. See http://sentry.support.akvo-ops.org/rsr/live/group/967/.



Discussion:

Resolving patch:
diff --git a/akvo/rsr/models/user.py b/akvo/rsr/models/user.py
--- a/akvo/rsr/models/user.py
+++ b/akvo/rsr/models/user.py
@@ -222,17 +222,8 @@ def set_is_org_admin(self, org, set_it):
             employment.group.delete()
 
     def get_admin_employment_orgs(self):
-        from .employment import Employment
-        from .organisation import Organisation
-
-        employments = Employment.objects.filter(user=self)
-        admin_employment_orgs = Organisation.objects.none()
-
-        for e in employments:
-            if e.group == Group.objects.get(name='Admins') and e.is_approved:
-                admin_employment_orgs = admin_employment_orgs | e.organisation
-
-        return admin_employment_orgs
+        employments = Employment.objects.filter(user=self, is_approved=True, group__name='Admins')
+        return employments.organisations()
 
     def get_owned_org_users(self):
         owned_organisation_users = []


Test patch:
Repository: akvo/akvo-rsr

Issue:
Unnecessary migrations are created for IatiImport.mapper_prefix
The choices for the `mapper_prefix` field are populated using a function that lists the sub-packages of `akvo.iati.imports.mappers`.  But, since the function does a directory listing, the order of packages can change and cause a new migration to be required. 

The function should return the sub-packages sorted, to fix this. 



Discussion:

Resolving patch:
diff --git a/akvo/codelists/migrations/0004_auto_20160920_1045.py b/akvo/codelists/migrations/0004_auto_20160920_1045.py
new file mode 100644
--- /dev/null
+++ b/akvo/codelists/migrations/0004_auto_20160920_1045.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('codelists', '0003_auto_20160226_1131'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='country',
+            options={'ordering': ('-version', 'name', 'code'), 'verbose_name': 'country', 'verbose_name_plural': 'countries'},
+        ),
+    ]
diff --git a/akvo/rsr/migrations/0084_auto_20160920_1045.py b/akvo/rsr/migrations/0084_auto_20160920_1045.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/migrations/0084_auto_20160920_1045.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('rsr', '0083_auto_20160816_0950'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='projecteditorvalidation',
+            name='action',
+            field=models.PositiveSmallIntegerField(db_index=True, verbose_name='action', choices=[(1, 'Mandatory'), (2, 'Hidden')]),
+            preserve_default=True,
+        ),
+    ]
diff --git a/akvo/rsr/models/iati_import.py b/akvo/rsr/models/iati_import.py
--- a/akvo/rsr/models/iati_import.py
+++ b/akvo/rsr/models/iati_import.py
@@ -30,7 +30,7 @@ def is_package(d):
 def custom_mappers():
     "Create a list of available custom mapper, for use in the admin"
     from ...iati.imports import mappers
-    subs = get_subpackages(mappers)
+    subs = sorted(get_subpackages(mappers))
     return [(sub, sub) for sub in subs]
 
 import logging


Test patch:
Repository: akvo/akvo-rsr

Issue:
Show the group associate with an Employment in the admin interface
Employments look like duplicates to the user, since the Group is not shown. See #2374 
![screenshot_132](https://cloud.githubusercontent.com/assets/142613/18669760/d9bce404-7f3c-11e6-8eb5-a0151c5d18d6.png)



Discussion:

Resolving patch:
diff --git a/akvo/rsr/admin.py b/akvo/rsr/admin.py
--- a/akvo/rsr/admin.py
+++ b/akvo/rsr/admin.py
@@ -1352,8 +1352,8 @@ class KeywordAdmin(admin.ModelAdmin):
 
 class EmploymentAdmin(admin.ModelAdmin):
     model = get_model('rsr', 'Employment')
-    list_display = ('__unicode__', 'user', 'organisation', 'is_approved', 'iati_country',
-                    'job_title')
+    list_display = ('__unicode__', 'user', 'organisation', 'group', 'is_approved',
+                    'iati_country', 'job_title')
     list_filter = ('is_approved', 'organisation')
     search_fields = ('organisation__name', 'organisation__long_name', 'user__username')
 


Test patch:
Repository: akvo/akvo-rsr

Issue:
Show error message if image file is too big when placing update (estimate: 6)
Currently, placing an update fails silently when the image attached is too big. We should add a nice error message for that.



Discussion:
@nadiagorchakova Can you remind me if this issue is for the RSR website or for Up app? 

If this is for the web-site, this [discussion seems relevant](https://github.com/akvo/akvo-rsr/issues/324).  But, the limit for the web-site has been made [way higher](https://github.com/akvo/akvo-provisioning/issues/277), so this is no longer an issue. 

We could add a front-end check, but I think this is not all that important anymore. Thoughts? /cc @zzgvh 

@punchagan The issue is for RSR website.

Right now RSR can handle images less than 3.5mb in size. However, as far as I know, partners with poor internet connection in project countries still face the issue. It takes too much time to load and the update page probably times out. 
I also see that in here https://github.com/akvo/akvo-rsr/issues/219 Kasper wrote some code to add help text on max image size. I don't see it implemented in RSR though. Would be helpful to have it implemented, in addition to the post-factum error message.


Resolving patch:
diff --git a/akvo/rsr/forms.py b/akvo/rsr/forms.py
--- a/akvo/rsr/forms.py
+++ b/akvo/rsr/forms.py
@@ -289,10 +289,13 @@ class ProjectUpdateForm(forms.ModelForm):
         'placeholder': _(u'Description'),
         }))
     language = forms.ChoiceField(choices=settings.LANGUAGES, initial='en')
-    photo = forms.ImageField(required=False, widget=forms.FileInput(attrs={
-        'class': 'input',
-        'size': '15',
-        }))
+    photo = forms.ImageField(required=False,
+                             widget=forms.FileInput(attrs={
+                                 'class': 'input',
+                                 'size': '15',
+                             }),
+                             help_text=_(u'Please upload an image of 2 MB or less.'),
+    )
     photo_caption = forms.CharField(label='', required=False, widget=forms.TextInput(attrs={
         'class': 'input',
         'size': '25',
diff --git a/akvo/rsr/views/project.py b/akvo/rsr/views/project.py
--- a/akvo/rsr/views/project.py
+++ b/akvo/rsr/views/project.py
@@ -442,6 +442,9 @@ def set_update(request, project_id, edit_mode=False, form_class=ProjectUpdateFor
             else:
                 update = updateform.save(project=project, user=request.user)
             return redirect(update.get_absolute_url())
+        else:
+            # Django forms takes care of this, and displays the errors!
+            pass
     else:
         updateform = form_class(instance=update)
 


Test patch:
Repository: akvo/akvo-rsr

Issue:
akvo.rest.fields in from_native AttributeError: 'NoneType' object has no attribute 'name'
http://sentry.support.akvo-ops.org/rsr/live/group/1017/

Bug introduced in 1aa60508350d4477c1f0964db7f3c124d9d1bc01


Discussion:

Resolving patch:
diff --git a/akvo/rest/fields.py b/akvo/rest/fields.py
--- a/akvo/rest/fields.py
+++ b/akvo/rest/fields.py
@@ -48,8 +48,10 @@ class Base64ImageField(ImageField):
         'png',
     )
     def from_native(self, base64_data):
+        if base64_data is None:
+            data = base64_data
         # Check if this is a base64 string
-        if isinstance(base64_data, basestring):
+        elif isinstance(base64_data, basestring):
             # Try to decode the file. Return validation error if it fails.
             try:
                 decoded_file = base64.b64decode(base64_data)


Test patch:
diff --git a/akvo/rsr/tests/rest/test_project_update.py b/akvo/rsr/tests/rest/test_project_update.py
--- a/akvo/rsr/tests/rest/test_project_update.py
+++ b/akvo/rsr/tests/rest/test_project_update.py
@@ -119,6 +119,22 @@ def test_rest_post_project_update(self):
                                })
         self.assertEqual(response.status_code, 201)
 
+    def test_rest_post_project_update_photo_none(self):
+        """
+        Checks posting a project update with photo being None
+        """
+
+        self.c.login(username=self.user.username, password='password')
+        response = self.c.post('/rest/v1/project_update/?format=json',
+                               json.dumps({
+                                   'project': self.project.pk,
+                                   'user': self.user.pk,
+                                   'title': 'Allowed',
+                                   'photo': None,
+                               }),
+                               content_type='application/json')
+        self.assertEqual(response.status_code, 201)
+
     def test_rest_post_project_update_wmf_string(self):
         """
         Checks posting a project update with a WMF photo base64 encoded.
Repository: akvo/akvo-rsr

Issue:
No users shown in user management page
When an employment doesn't have a group (See #2122, #2374), the User management page in MyRSR doesn't display any of the users.  Some js assumes that all employments have a group.


Discussion:

Resolving patch:
diff --git a/akvo/rsr/migrations/0087_auto_20161110_0920.py b/akvo/rsr/migrations/0087_auto_20161110_0920.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/migrations/0087_auto_20161110_0920.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def fix_employment_groups(apps, schema_editor):
+    # We can't import the Employment or Group model directly as it may be a
+    # newer version than this migration expects. We use the historical version.
+    Group = apps.get_model("auth", "Group")
+    Employment = apps.get_model("rsr", "Employment")
+    for employment in Employment.objects.filter(group=None):
+        employment.group = Group.objects.get(name='Users')
+        employment.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('rsr', '0086_auto_20160921_0947'),
+    ]
+
+    operations = [
+        migrations.RunPython(fix_employment_groups),
+    ]


Test patch:
Repository: akvo/akvo-rsr

Issue:
Legacy API user organisation may be unapproved (estimate: 3)
#2364 fixed the problem where Up version 1.5 shows random organisations for Update authors. However, the org id supplied may be for an organisation for which the user is not (yet) approved, which is potentially confusing. It would be be better if the legacy org was chosen only from those approved.



Discussion:
Do newer versions of up try to figure out the "correct" organisation, i.e. an org the user is employed by that is actually a partner of the project the update is made for? I see this isn't relevant for old version of Up, but if we fix this we might as well look at the whole of this issue.

The latest app does seem to behave correctly w.r.t what projects are shown to a user -- projects from unapproved organisations don't seem to be shown. I tested this on the app, but @stellanl, please correct me if I'm wrong

Resolving patch:
diff --git a/akvo/rsr/models/user.py b/akvo/rsr/models/user.py
--- a/akvo/rsr/models/user.py
+++ b/akvo/rsr/models/user.py
@@ -307,7 +307,7 @@ def my_projects(self):
         return self.organisations.all().all_projects()
 
     def first_organisation(self):
-        all_orgs = self.organisations.all()
+        all_orgs = self.approved_organisations()
         if all_orgs:
             return all_orgs[0]
         else:


Test patch:
Repository: akvo/akvo-rsr

Issue:
Importing Results does not import IndicatorReferences
Reported by Annabelle


Discussion:

Resolving patch:
diff --git a/akvo/rsr/models/project.py b/akvo/rsr/models/project.py
--- a/akvo/rsr/models/project.py
+++ b/akvo/rsr/models/project.py
@@ -1348,6 +1348,9 @@ def add_indicator(self, result, indicator):
         for period in indicator.periods.all():
             self.add_period(self_indicator, period)
 
+        for reference in indicator.references.all():
+            self.add_reference(self_indicator, reference)
+
     def add_period(self, indicator, period):
         get_model('rsr', 'IndicatorPeriod').objects.create(
             indicator=indicator,
@@ -1358,6 +1361,14 @@ def add_period(self, indicator, period):
             actual_comment=period.actual_comment
         )
 
+    def add_reference(self, indicator, reference):
+        get_model('rsr', 'IndicatorReference').objects.create(
+            indicator=indicator,
+            reference=reference.reference,
+            vocabulary=reference.vocabulary,
+            vocabulary_uri=reference.vocabulary_uri,
+        )
+
     def has_results(self):
         for result in self.results.all():
             if result.title or result.type or result.aggregation_status or result.description:


Test patch:
diff --git a/akvo/rsr/tests/results_framework/test_results_framework.py b/akvo/rsr/tests/results_framework/test_results_framework.py
--- a/akvo/rsr/tests/results_framework/test_results_framework.py
+++ b/akvo/rsr/tests/results_framework/test_results_framework.py
@@ -10,7 +10,7 @@
 import datetime
 
 from akvo.rsr.models import (Project, PublishingStatus, Result, Indicator, IndicatorPeriod,
-                             IndicatorPeriodData, User, RelatedProject)
+                             IndicatorPeriodData, IndicatorReference, User, RelatedProject)
 
 from django.test import TestCase
 
@@ -72,6 +72,11 @@ def setUp(self):
             period_end=datetime.date.today() + datetime.timedelta(days=1),
             target_value="100"
         )
+        self.reference = IndicatorReference.objects.create(
+            indicator=indicator,
+            reference='ABC',
+            vocabulary='1',
+        )
 
         # Import results framework into child
         self.import_status, self.import_message = self.child_project.import_results()
@@ -87,6 +92,10 @@ def test_import_in_child(self):
             indicator__result__project=self.child_project).first()
         self.assertEqual(child_period.indicator.result.parent_result, self.period.indicator.result)
         self.assertEqual(child_period.parent_period(), self.period)
+        child_reference = child_period.indicator.references.first()
+        self.assertEqual(child_reference.reference, self.reference.reference)
+        self.assertEqual(child_reference.vocabulary, self.reference.vocabulary)
+        self.assertEqual(child_reference.vocabulary_uri, self.reference.vocabulary_uri)
 
     def test_update(self):
         """
Repository: akvo/akvo-rsr

Issue:
Invalid HTTP_HOST header: '*.live.akvo-ops.org'. 
The domain name provided is not valid according to RFC 1034/1035.


Discussion:

Resolving patch:
diff --git a/akvo/rsr/middleware.py b/akvo/rsr/middleware.py
--- a/akvo/rsr/middleware.py
+++ b/akvo/rsr/middleware.py
@@ -112,14 +112,14 @@ class HostDispatchMiddleware(object):
     def process_request(self, request):
         """Route on request."""
         request.rsr_page = None
-        host = request.get_host()
-
-        # Make sure host is valid - otherwise redirect to RSR_DOMAIN.
-        # Do nothing if called on "normal" RSR host.
         try:
+            # Make sure host is valid - otherwise redirect to RSR_DOMAIN.
+            # Do nothing if called on "normal" RSR host.
+            host = request.get_host()
             if _is_rsr_host(host):
                 return None
         except DisallowedHost:
+            request.META['HTTP_HOST'] = settings.RSR_DOMAIN
             return redirect("http://{}".format(settings.RSR_DOMAIN))
 
         # Check if called on naked app domain - if so redirect


Test patch:
diff --git a/akvo/rsr/tests/test_middleware.py b/akvo/rsr/tests/test_middleware.py
--- a/akvo/rsr/tests/test_middleware.py
+++ b/akvo/rsr/tests/test_middleware.py
@@ -46,24 +46,29 @@ class HostHeaderTestCase(TestCase):
 
     """Testing boot traffic."""
 
-    def setUp(self):
-        """Setup."""
-        self.c = Client(HTTP_HOST='_')
-
     def test_underscore_host(self):
         """When host is '_'."""
+        self.c = Client(HTTP_HOST='_')
         resp = self.c.get('/')
-        self.assertEqual(resp.status_code, 400)
+        self.assertEqual(resp.status_code, 302)
 
     def test_empy_host(self):
         """When host is ''."""
-        resp = self.c.get('')
-        self.assertEqual(resp.status_code, 400)
+        self.c = Client(HTTP_HOST='')
+        resp = self.c.get('/')
+        self.assertEqual(resp.status_code, 302)
 
     def test_oddchar_host(self):
         """When host is ''."""
-        resp = self.c.get('$')
-        self.assertEqual(resp.status_code, 400)
+        self.c = Client(HTTP_HOST='$')
+        resp = self.c.get('/')
+        self.assertEqual(resp.status_code, 302)
+
+    def test_wildcard_host(self):
+        """When host is ''*.live.akvo-ops.org"""
+        self.c = Client(HTTP_HOST='*.live.akvo-ops.org')
+        resp = self.c.get('/')
+        self.assertEqual(resp.status_code, 302)
 
 
 class InValidStockRSRTestCase(TestCase):
Repository: akvo/akvo-rsr

Issue:
More 504s: on the results framework page
@Geerts reports on Skype: 504 Gateway timeout hunter strikes again: http://rsr.test.akvo.org/rest/v1/indicator_period_data_framework/?format=json&period__indicator__result__project=2780

Via: http://rsr.test.akvo.org/en/myrsr/results/2780/#results,13323,5679


Discussion:

Resolving patch:
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
@@ -30,7 +30,13 @@ class IndicatorPeriodDataViewSet(PublicProjectViewSet):
 class IndicatorPeriodDataFrameworkViewSet(PublicProjectViewSet):
     """
     """
-    queryset = IndicatorPeriodData.objects.all()
+    queryset = IndicatorPeriodData.objects.select_related(
+        'period',
+        'user'
+    ).prefetch_related(
+        'comments',
+        'comments__user'
+    ).all()
     serializer_class = IndicatorPeriodDataFrameworkSerializer
     project_relation = 'period__indicator__result__project__'
 
diff --git a/akvo/rest/views/partnership.py b/akvo/rest/views/partnership.py
--- a/akvo/rest/views/partnership.py
+++ b/akvo/rest/views/partnership.py
@@ -14,7 +14,7 @@
 class PartnershipViewSet(PublicProjectViewSet):
     """
     """
-    queryset = Partnership.objects.all()
+    queryset = Partnership.objects.select_related('organisation', 'project').all()
     serializer_class = PartnershipSerializer
 
     def get_queryset(self):


Test patch: