Merge pull request #736 from taigaio/Improving-project-deletion

Improving-project-deletion
remotes/origin/issue/4795/notification_even_they_are_disabled
David Barragán Merino 2016-05-30 17:57:57 +02:00
commit a1f52e9a72
6 changed files with 88 additions and 5 deletions

View File

@ -20,6 +20,7 @@ from easy_thumbnails.source_generators import pil_image
from dateutil.relativedelta import relativedelta
from django.apps import apps
from django.conf import settings
from django.db.models import signals, Prefetch
from django.db.models import Value as V
from django.db.models.functions import Coalesce
@ -442,9 +443,13 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
self.pre_delete(obj)
self.pre_conditions_on_delete(obj)
obj.delete_related_content()
obj.delete()
self.post_delete(obj)
services.orphan_project(obj)
if settings.CELERY_ENABLED:
services.delete_project.delay(obj.id)
else:
services.delete_project(obj.id)
return response.NoContent()

View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-05-30 10:04
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('projects', '0042_auto_20160525_0911'),
]
operations = [
migrations.AlterField(
model_name='project',
name='owner',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_projects', to=settings.AUTH_USER_MODEL, verbose_name='owner'),
),
]

View File

@ -157,7 +157,7 @@ class Project(ProjectDefaults, TaggedMixin, models.Model):
default=timezone.now)
modified_date = models.DateTimeField(null=False, blank=False,
verbose_name=_("modified date"))
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=False, blank=False,
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True,
related_name="owned_projects", verbose_name=_("owner"))
members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="projects",
through="Membership", verbose_name=_("members"),

View File

@ -47,6 +47,8 @@ from .projects import check_if_project_privacity_can_be_changed
from .projects import check_if_project_can_be_created_or_updated
from .projects import check_if_project_can_be_transfered
from .projects import check_if_project_is_out_of_owner_limits
from .projects import orphan_project
from .projects import delete_project
from .stats import get_stats_for_project_issues
from .stats import get_stats_for_project

View File

@ -15,8 +15,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.apps import apps
from django.utils.translation import ugettext as _
from taiga.celery import app
ERROR_MAX_PUBLIC_PROJECTS_MEMBERSHIPS = 'max_public_projects_memberships'
ERROR_MAX_PRIVATE_PROJECTS_MEMBERSHIPS = 'max_private_projects_memberships'
@ -151,3 +152,21 @@ def check_if_project_is_out_of_owner_limits(project):
return True
return False
def orphan_project(project):
project.memberships.filter(user=project.owner).delete()
project.owner = None
project.save()
@app.task
def delete_project(project_id):
Project = apps.get_model("projects", "Project")
try:
project = Project.objects.get(id=project_id)
except Project.DoesNotExist:
return
project.delete_related_content()
project.delete()

View File

@ -19,6 +19,8 @@ from easy_thumbnails.files import generate_all_aliases, get_thumbnailer
import os.path
import pytest
from unittest import mock
pytestmark = pytest.mark.django_db
class ExpiredSigner(signing.TimestampSigner):
@ -1814,3 +1816,36 @@ def test_public_project_when_project_has_unlimited_members(client):
project.owner.max_memberships_public_projects = None
assert check_if_project_is_out_of_owner_limits(project) == False
def test_delete_project_with_celery_enabled(client, settings):
settings.CELERY_ENABLED = True
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
url = reverse("projects-detail", args=(project.id,))
client.login(user)
#delete_project task should have been launched
with mock.patch('taiga.projects.services.delete_project') as delete_project_mock:
response = client.json.delete(url)
assert response.status_code == 204
project = Project.objects.get(id=project.id)
assert project.owner == None
assert project.memberships.count() == 0
delete_project_mock.delay.assert_called_once_with(project.id)
def test_delete_project_with_celery_disabled(client, settings):
settings.CELERY_ENABLED = False
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
url = reverse("projects-detail", args=(project.id,))
client.login(user)
response = client.json.delete(url)
assert response.status_code == 204
assert Project.objects.filter(id=project.id).count() == 0