Adding leave project API

remotes/origin/enhancement/email-actions
Alejandro Alonso 2014-11-20 09:26:46 +01:00 committed by Jesús Espino
parent e7b963a674
commit c9fc2268d0
5 changed files with 72 additions and 3 deletions

View File

@ -154,6 +154,13 @@ class ProjectViewSet(ModelCrudViewSet):
template.save() template.save()
return Response(serializers.ProjectTemplateSerializer(template).data, status=201) return Response(serializers.ProjectTemplateSerializer(template).data, status=201)
@detail_route(methods=['post'])
def leave(self, request, pk=None):
project = self.get_object()
self.check_permissions(request, 'leave', project)
services.remove_member(project, user=request.user)
return Response(status=status.HTTP_200_OK)
def pre_save(self, obj): def pre_save(self, obj):
if not obj.id: if not obj.id:
obj.owner = self.request.user obj.owner = self.request.user

View File

@ -13,10 +13,35 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.utils.translation import ugettext_lazy as _
from taiga.base.api.permissions import (TaigaResourcePermission, HasProjectPerm, from taiga.base.api.permissions import (TaigaResourcePermission, HasProjectPerm,
IsAuthenticated, IsProjectOwner, IsAuthenticated, IsProjectOwner,
AllowAny, IsSuperUser) AllowAny, IsSuperUser, PermissionComponent)
from taiga.base import exceptions as exc
from taiga.projects.models import Membership
class CanLeaveProject(PermissionComponent):
def check_permissions(self, request, view, obj=None):
if not obj or not request.user.is_authenticated():
return False
try:
membership = Membership.objects.get(user=request.user, project=obj)
other_admin_memberships_count = Membership.objects\
.exclude(id=membership.id)\
.filter(project=obj, is_owner=True)\
.count()
# The project need at least one owner
if membership.is_owner and other_admin_memberships_count == 0:
raise exc.PermissionDenied(_("You can't leave the project if there are no more owners"))
return True
except Membership.DoesNotExist:
return False
class ProjectPermission(TaigaResourcePermission): class ProjectPermission(TaigaResourcePermission):
@ -37,6 +62,7 @@ class ProjectPermission(TaigaResourcePermission):
tags_colors_perms = HasProjectPerm('view_project') tags_colors_perms = HasProjectPerm('view_project')
fans_perms = HasProjectPerm('view_project') fans_perms = HasProjectPerm('view_project')
create_template_perms = IsSuperUser() create_template_perms = IsSuperUser()
leave_perms = CanLeaveProject()
class MembershipPermission(TaigaResourcePermission): class MembershipPermission(TaigaResourcePermission):

View File

@ -34,6 +34,7 @@ from .stats import get_member_stats_for_project
from .members import create_members_in_bulk from .members import create_members_in_bulk
from .members import get_members_from_bulk from .members import get_members_from_bulk
from .members import remove_member
from .invitations import send_invitation from .invitations import send_invitation
from .invitations import find_invited_user from .invitations import find_invited_user

View File

@ -2,7 +2,6 @@ from taiga.base.utils import db, text
from .. import models from .. import models
def get_members_from_bulk(bulk_data, **additional_fields): def get_members_from_bulk(bulk_data, **additional_fields):
"""Convert `bulk_data` into a list of members. """Convert `bulk_data` into a list of members.
@ -31,3 +30,7 @@ def create_members_in_bulk(bulk_data, callback=None, precall=None, **additional_
members = get_members_from_bulk(bulk_data, **additional_fields) members = get_members_from_bulk(bulk_data, **additional_fields)
db.save_in_bulk(members, callback, precall) db.save_in_bulk(members, callback, precall)
return members return members
def remove_member(project, user):
models.Membership.objects.get(project=project, user=user).delete()

View File

@ -160,3 +160,35 @@ def test_get_closed_bugs_per_member_stats():
assert stats["closed_tasks"][membership_1.user.id] == 1 assert stats["closed_tasks"][membership_1.user.id] == 1
assert stats["closed_tasks"][membership_2.user.id] == 0 assert stats["closed_tasks"][membership_2.user.id] == 0
def test_leave_project_valid_membership(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create()
role = f.RoleFactory.create(project=project, permissions=["view_project"])
f.MembershipFactory.create(project=project, user=user, role=role)
client.login(user)
url = reverse("projects-leave", args=(project.id,))
response = client.post(url)
assert response.status_code == 200
def test_leave_project_valid_membership_only_owner(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create()
role = f.RoleFactory.create(project=project, permissions=["view_project"])
f.MembershipFactory.create(project=project, user=user, role=role, is_owner=True)
client.login(user)
url = reverse("projects-leave", args=(project.id,))
response = client.post(url)
assert response.status_code == 403
assert json.loads(response.content)["_error_message"] == "You can't leave the project if there are no more owners"
def test_leave_project_invalid_membership(client):
user = f.UserFactory.create()
project = f.ProjectFactory()
client.login(user)
url = reverse("projects-leave", args=(project.id,))
response = client.post(url)
assert response.status_code == 404