We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Prevent automatic publishing of projects
## Test plan

GIVEN a project that is going to be published
WHEN the project is published
THEN a notification mail will be sent to Kasper
## Issue description

Somehow there are projects (mainly from Commonsites and Akvo) that get published automatically, even though they shouldn't be. This should be prevented and fixed.

Note; I can't find the reason why this happens. I suspect the API, but then again, this only happens for Akvo and Commonsites projects. Therefore I'll monitor it for now.


--- 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/rsr/models/publishing_status.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 from django.core.exceptions import ValidationError
8 from django.db import models
9 from django.utils.translation import ugettext_lazy as _
10 
11 from ..fields import ValidXMLCharField
12 
13 
14 class PublishingStatus(models.Model):
15     """Keep track of publishing status."""
16     STATUS_PUBLISHED = 'published'
17     STATUS_UNPUBLISHED = 'unpublished'
18     PUBLISHING_STATUS = (
19         (STATUS_UNPUBLISHED, _(u'Unpublished')),
20         (STATUS_PUBLISHED, _(u'Published')),
21     )
22 
23     project = models.OneToOneField('Project',)
24     status = ValidXMLCharField(max_length=30,
25                                choices=PUBLISHING_STATUS,
26                                db_index=True, default=STATUS_UNPUBLISHED)
27 
28     def clean(self):
29         """Projects can only be published, when several checks have been performed."""
30         if self.status == 'published':
31             validation_errors = []
32 
33             if not self.project.title:
34                 validation_errors.append(
35                     ValidationError(_('Project needs to have a title.'),
36                                     code='title')
37                 )
38 
39             if not self.project.subtitle:
40                 validation_errors.append(
41                     ValidationError(_('Project needs to have a subtitle.'),
42                                     code='subtitle')
43                 )
44 
45             if not self.project.project_plan_summary:
46                 validation_errors.append(
47                     ValidationError(_('Project needs to have the project plan summary filled in.'),
48                                     code='summary')
49                 )
50 
51             if not self.project.goals_overview:
52                 validation_errors.append(
53                     ValidationError(_('Project needs to have the goals overview field filled in.'),
54                                     code='goals_overview')
55                 )
56 
57             if not self.project.date_start_planned:
58                 validation_errors.append(
59                     ValidationError(
60                         _('Project needs to have the planned start date field filled in.'),
61                         code='goals_overview')
62                 )
63 
64             if not self.project.partners:
65                 validation_errors.append(
66                     ValidationError(_('Project needs to have at least one valid partner.'),
67                                     code='partners')
68                 )
69             elif not self.project.partnerships.filter(
70                     partner_type__in=['field', 'funding', 'support']
71             ).exists():
72                 validation_errors.append(
73                     ValidationError(
74                         _('Project needs to have at least one field, funding or support partner.'),
75                         code='partners'
76                     )
77                 )
78             else:
79                 for funding_partner in self.project.partnerships.filter(partner_type='funding'):
80                     if not funding_partner.funding_amount:
81                         validation_errors.append(
82                             ValidationError(_('All funding partners should have a funding amount.'),
83                                             code='partners'
84                             )
85                         )
86                         break
87 
88             if not self.project.sync_owner:
89                 validation_errors.append(
90                     ValidationError(_('Project needs to have a reporting organisation.'),
91                                     code='reporting_org')
92                 )
93 
94             if not self.project.current_image:
95                 validation_errors.append(
96                     ValidationError(_('Project needs to have a photo.'),
97                                     code='current_image')
98                 )
99 
100             if not self.project.locations.all():
101                 validation_errors.append(
102                     ValidationError(_('Project needs to have at least one location.'),
103                                     code='location')
104                 )
105             else:
106                 for location in self.project.locations.all():
107                     if not location.latitude or not location.longitude or not location.country:
108                         validation_errors.append(
109                             ValidationError(
110                                 _('All locations need to have a latitude, longitude and country '
111                                   'specified.'),
112                                 code='location')
113                         )
114                         break
115 
116             if not self.project.budget_items.all():
117                 validation_errors.append(
118                     ValidationError(_('Project needs to have at least one budget item.'),
119                                     code='budget_item')
120                 )
121             elif not self.project.budget_items.filter(amount__gt=0).exists():
122                 validation_errors.append(
123                     ValidationError(
124                         _('Project needs to have at least one budget item with an amount.'),
125                         code='budget_item'
126                     )
127                 )
128 
129             if not self.project.sectors.all():
130                 validation_errors.append(
131                     ValidationError(_('Project needs to have at least one sector.'),
132                                     code='sector')
133                 )
134             else:
135                 for sector in self.project.sectors.all():
136                     if not sector.sector_code:
137                         validation_errors.append(
138                             ValidationError(_('All sectors need to have a sector code.'),
139                                             code='sector')
140                         )
141                         break
142 
143             if validation_errors:
144                 raise ValidationError(validation_errors)
145 
146     class Meta:
147         app_label = 'rsr'
148         verbose_name = _(u'publishing status')
149         verbose_name_plural = _(u'publishing statuses')
150         ordering = ('-status', 'project')
151
```
--- 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/rsr/models/publishing_status.py b/akvo/rsr/models/publishing_status.py
--- a/akvo/rsr/models/publishing_status.py
+++ b/akvo/rsr/models/publishing_status.py
@@ -4,8 +4,12 @@
 # See more details in the license.txt file located at the root folder of the Akvo RSR module.
 # For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
 
+from django.conf import settings
 from django.core.exceptions import ValidationError
+from django.core.mail import send_mail
 from django.db import models
+from django.db.models.signals import post_save
+from django.dispatch import receiver
 from django.utils.translation import ugettext_lazy as _
 
 from ..fields import ValidXMLCharField
@@ -148,3 +152,15 @@
         verbose_name = _(u'publishing status')
         verbose_name_plural = _(u'publishing statuses')
         ordering = ('-status', 'project')
+
+
+@receiver(post_save, sender=PublishingStatus)
+def update_denormalized_project(sender, **kwargs):
+    "Send notification that a project is published."
+    publishing_status = kwargs['instance']
+    if publishing_status.status == PublishingStatus.STATUS_PUBLISHED:
+        send_mail(
+            'Project %s has been published' % str(publishing_status.project.pk),
+            '', getattr(settings, "DEFAULT_FROM_EMAIL", "noreply@akvo.org"),
+            getattr(settings, "NOTIFY_PUBLISH", ["kasper@akvo.org"])
+        )

{"golden_diff": "diff --git a/akvo/rsr/models/publishing_status.py b/akvo/rsr/models/publishing_status.py\n--- a/akvo/rsr/models/publishing_status.py\n+++ b/akvo/rsr/models/publishing_status.py\n@@ -4,8 +4,12 @@\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+from django.conf import settings\n from django.core.exceptions import ValidationError\n+from django.core.mail import send_mail\n from django.db import models\n+from django.db.models.signals import post_save\n+from django.dispatch import receiver\n from django.utils.translation import ugettext_lazy as _\n \n from ..fields import ValidXMLCharField\n@@ -148,3 +152,15 @@\n         verbose_name = _(u'publishing status')\n         verbose_name_plural = _(u'publishing statuses')\n         ordering = ('-status', 'project')\n+\n+\n+@receiver(post_save, sender=PublishingStatus)\n+def update_denormalized_project(sender, **kwargs):\n+    \"Send notification that a project is published.\"\n+    publishing_status = kwargs['instance']\n+    if publishing_status.status == PublishingStatus.STATUS_PUBLISHED:\n+        send_mail(\n+            'Project %s has been published' % str(publishing_status.project.pk),\n+            '', getattr(settings, \"DEFAULT_FROM_EMAIL\", \"noreply@akvo.org\"),\n+            getattr(settings, \"NOTIFY_PUBLISH\", [\"kasper@akvo.org\"])\n+        )\n", "issue": "Prevent automatic publishing of projects\n## Test plan\n\nGIVEN a project that is going to be published\nWHEN the project is published\nTHEN a notification mail will be sent to Kasper\n## Issue description\n\nSomehow there are projects (mainly from Commonsites and Akvo) that get published automatically, even though they shouldn't be. This should be prevented and fixed.\n\nNote; I can't find the reason why this happens. I suspect the API, but then again, this only happens for Akvo and Commonsites projects. Therefore I'll monitor it for now.\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\nfrom django.core.exceptions import ValidationError\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom ..fields import ValidXMLCharField\n\n\nclass PublishingStatus(models.Model):\n    \"\"\"Keep track of publishing status.\"\"\"\n    STATUS_PUBLISHED = 'published'\n    STATUS_UNPUBLISHED = 'unpublished'\n    PUBLISHING_STATUS = (\n        (STATUS_UNPUBLISHED, _(u'Unpublished')),\n        (STATUS_PUBLISHED, _(u'Published')),\n    )\n\n    project = models.OneToOneField('Project',)\n    status = ValidXMLCharField(max_length=30,\n                               choices=PUBLISHING_STATUS,\n                               db_index=True, default=STATUS_UNPUBLISHED)\n\n    def clean(self):\n        \"\"\"Projects can only be published, when several checks have been performed.\"\"\"\n        if self.status == 'published':\n            validation_errors = []\n\n            if not self.project.title:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a title.'),\n                                    code='title')\n                )\n\n            if not self.project.subtitle:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a subtitle.'),\n                                    code='subtitle')\n                )\n\n            if not self.project.project_plan_summary:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have the project plan summary filled in.'),\n                                    code='summary')\n                )\n\n            if not self.project.goals_overview:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have the goals overview field filled in.'),\n                                    code='goals_overview')\n                )\n\n            if not self.project.date_start_planned:\n                validation_errors.append(\n                    ValidationError(\n                        _('Project needs to have the planned start date field filled in.'),\n                        code='goals_overview')\n                )\n\n            if not self.project.partners:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one valid partner.'),\n                                    code='partners')\n                )\n            elif not self.project.partnerships.filter(\n                    partner_type__in=['field', 'funding', 'support']\n            ).exists():\n                validation_errors.append(\n                    ValidationError(\n                        _('Project needs to have at least one field, funding or support partner.'),\n                        code='partners'\n                    )\n                )\n            else:\n                for funding_partner in self.project.partnerships.filter(partner_type='funding'):\n                    if not funding_partner.funding_amount:\n                        validation_errors.append(\n                            ValidationError(_('All funding partners should have a funding amount.'),\n                                            code='partners'\n                            )\n                        )\n                        break\n\n            if not self.project.sync_owner:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a reporting organisation.'),\n                                    code='reporting_org')\n                )\n\n            if not self.project.current_image:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a photo.'),\n                                    code='current_image')\n                )\n\n            if not self.project.locations.all():\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one location.'),\n                                    code='location')\n                )\n            else:\n                for location in self.project.locations.all():\n                    if not location.latitude or not location.longitude or not location.country:\n                        validation_errors.append(\n                            ValidationError(\n                                _('All locations need to have a latitude, longitude and country '\n                                  'specified.'),\n                                code='location')\n                        )\n                        break\n\n            if not self.project.budget_items.all():\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one budget item.'),\n                                    code='budget_item')\n                )\n            elif not self.project.budget_items.filter(amount__gt=0).exists():\n                validation_errors.append(\n                    ValidationError(\n                        _('Project needs to have at least one budget item with an amount.'),\n                        code='budget_item'\n                    )\n                )\n\n            if not self.project.sectors.all():\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one sector.'),\n                                    code='sector')\n                )\n            else:\n                for sector in self.project.sectors.all():\n                    if not sector.sector_code:\n                        validation_errors.append(\n                            ValidationError(_('All sectors need to have a sector code.'),\n                                            code='sector')\n                        )\n                        break\n\n            if validation_errors:\n                raise ValidationError(validation_errors)\n\n    class Meta:\n        app_label = 'rsr'\n        verbose_name = _(u'publishing status')\n        verbose_name_plural = _(u'publishing statuses')\n        ordering = ('-status', 'project')\n", "path": "akvo/rsr/models/publishing_status.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\nfrom django.conf import settings\nfrom django.core.exceptions import ValidationError\nfrom django.core.mail import send_mail\nfrom django.db import models\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom ..fields import ValidXMLCharField\n\n\nclass PublishingStatus(models.Model):\n    \"\"\"Keep track of publishing status.\"\"\"\n    STATUS_PUBLISHED = 'published'\n    STATUS_UNPUBLISHED = 'unpublished'\n    PUBLISHING_STATUS = (\n        (STATUS_UNPUBLISHED, _(u'Unpublished')),\n        (STATUS_PUBLISHED, _(u'Published')),\n    )\n\n    project = models.OneToOneField('Project',)\n    status = ValidXMLCharField(max_length=30,\n                               choices=PUBLISHING_STATUS,\n                               db_index=True, default=STATUS_UNPUBLISHED)\n\n    def clean(self):\n        \"\"\"Projects can only be published, when several checks have been performed.\"\"\"\n        if self.status == 'published':\n            validation_errors = []\n\n            if not self.project.title:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a title.'),\n                                    code='title')\n                )\n\n            if not self.project.subtitle:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a subtitle.'),\n                                    code='subtitle')\n                )\n\n            if not self.project.project_plan_summary:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have the project plan summary filled in.'),\n                                    code='summary')\n                )\n\n            if not self.project.goals_overview:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have the goals overview field filled in.'),\n                                    code='goals_overview')\n                )\n\n            if not self.project.date_start_planned:\n                validation_errors.append(\n                    ValidationError(\n                        _('Project needs to have the planned start date field filled in.'),\n                        code='goals_overview')\n                )\n\n            if not self.project.partners:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one valid partner.'),\n                                    code='partners')\n                )\n            elif not self.project.partnerships.filter(\n                    partner_type__in=['field', 'funding', 'support']\n            ).exists():\n                validation_errors.append(\n                    ValidationError(\n                        _('Project needs to have at least one field, funding or support partner.'),\n                        code='partners'\n                    )\n                )\n            else:\n                for funding_partner in self.project.partnerships.filter(partner_type='funding'):\n                    if not funding_partner.funding_amount:\n                        validation_errors.append(\n                            ValidationError(_('All funding partners should have a funding amount.'),\n                                            code='partners'\n                            )\n                        )\n                        break\n\n            if not self.project.sync_owner:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a reporting organisation.'),\n                                    code='reporting_org')\n                )\n\n            if not self.project.current_image:\n                validation_errors.append(\n                    ValidationError(_('Project needs to have a photo.'),\n                                    code='current_image')\n                )\n\n            if not self.project.locations.all():\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one location.'),\n                                    code='location')\n                )\n            else:\n                for location in self.project.locations.all():\n                    if not location.latitude or not location.longitude or not location.country:\n                        validation_errors.append(\n                            ValidationError(\n                                _('All locations need to have a latitude, longitude and country '\n                                  'specified.'),\n                                code='location')\n                        )\n                        break\n\n            if not self.project.budget_items.all():\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one budget item.'),\n                                    code='budget_item')\n                )\n            elif not self.project.budget_items.filter(amount__gt=0).exists():\n                validation_errors.append(\n                    ValidationError(\n                        _('Project needs to have at least one budget item with an amount.'),\n                        code='budget_item'\n                    )\n                )\n\n            if not self.project.sectors.all():\n                validation_errors.append(\n                    ValidationError(_('Project needs to have at least one sector.'),\n                                    code='sector')\n                )\n            else:\n                for sector in self.project.sectors.all():\n                    if not sector.sector_code:\n                        validation_errors.append(\n                            ValidationError(_('All sectors need to have a sector code.'),\n                                            code='sector')\n                        )\n                        break\n\n            if validation_errors:\n                raise ValidationError(validation_errors)\n\n    class Meta:\n        app_label = 'rsr'\n        verbose_name = _(u'publishing status')\n        verbose_name_plural = _(u'publishing statuses')\n        ordering = ('-status', 'project')\n\n\n@receiver(post_save, sender=PublishingStatus)\ndef update_denormalized_project(sender, **kwargs):\n    \"Send notification that a project is published.\"\n    publishing_status = kwargs['instance']\n    if publishing_status.status == PublishingStatus.STATUS_PUBLISHED:\n        send_mail(\n            'Project %s has been published' % str(publishing_status.project.pk),\n            '', getattr(settings, \"DEFAULT_FROM_EMAIL\", \"noreply@akvo.org\"),\n            getattr(settings, \"NOTIFY_PUBLISH\", [\"kasper@akvo.org\"])\n        )\n", "path": "akvo/rsr/models/publishing_status.py"}]}