diff --git a/taiga/projects/milestones/permissions.py b/taiga/projects/milestones/permissions.py index d039815a..805c5f23 100644 --- a/taiga/projects/milestones/permissions.py +++ b/taiga/projects/milestones/permissions.py @@ -15,7 +15,13 @@ # along with this program. If not, see . from taiga.base.api.permissions import (ResourcePermission, HasProjectPerm, - IsProjectOwner, AllowAny) + IsProjectOwner, AllowAny, + PermissionComponent) + + +class IsLastMilestone(PermissionComponent): + def check_permissions(self, request, view, obj=None): + return obj.project.milestones.filter(pk__gt=obj.pk).count() == 0 class MilestonePermission(ResourcePermission): @@ -24,6 +30,6 @@ class MilestonePermission(ResourcePermission): retrieve_perms = HasProjectPerm('view_milestones') create_perms = HasProjectPerm('add_milestone') update_perms = HasProjectPerm('modify_milestone') - destroy_perms = HasProjectPerm('delete_milestone') + destroy_perms = HasProjectPerm('delete_milestone') | (HasProjectPerm('delete_last_milestone') & IsLastMilestone()) list_perms = AllowAny() stats_perms = HasProjectPerm('view_milestones') diff --git a/tests/integration/resources_permissions/test_milestones_resources.py b/tests/integration/resources_permissions/test_milestones_resources.py index 6f5c1957..deedf10f 100644 --- a/tests/integration/resources_permissions/test_milestones_resources.py +++ b/tests/integration/resources_permissions/test_milestones_resources.py @@ -146,6 +146,29 @@ def test_milestone_delete(client, data): assert results == [401, 403, 403, 204] +def test_milestone_delete_last_milestone(client, data): + url_not_last_milestone = reverse('milestones-detail', kwargs={"pk": data.public_milestone.pk}) + + data.public_milestone2 = f.MilestoneFactory(project=data.public_project) + url_last_milestone = reverse('milestones-detail', kwargs={"pk": data.public_milestone2.pk}) + + data.public_membership.role.permissions = list(filter(lambda x: x != "delete_milestone", data.public_membership.role.permissions)) + data.public_membership.role.save() + + users = [ + None, + data.registered_user, + data.project_member_without_perms, + data.project_member_with_perms, + ] + results = helper_test_http_method(client, 'delete', url_not_last_milestone, None, users) + assert results == [401, 403, 403, 403] + results = helper_test_http_method(client, 'delete', url_last_milestone, None, users) + assert results == [401, 403, 403, 204] + results = helper_test_http_method(client, 'delete', url_not_last_milestone, None, users) + assert results == [401, 403, 403, 204] + + def test_milestone_list(client, data): url = reverse('milestones-list')