diff --git a/client/src/components/learningMentor/MyMentors.vue b/client/src/components/learningMentor/MyMentors.vue index 4f58c330..da3c5a45 100644 --- a/client/src/components/learningMentor/MyMentors.vue +++ b/client/src/components/learningMentor/MyMentors.vue @@ -51,9 +51,11 @@ const removeInvitation = async (invitationId: string) => { await refreshInvitations(); }; -const removeMentor = async (mentorId: string) => { +const userStore = useUserStore(); + +const removeMyMentor = async (mentorId: string) => { await useCSRFFetch( - `/api/mentor/${courseSession.value.id}/mentors/${mentorId}/leave` + `/api/mentor/${courseSession.value.id}/mentors/${mentorId}/remove/${userStore.id}` ).delete(); await refreshMentors(); }; @@ -127,7 +129,7 @@ const inviteMentor = async () => { {{ learningMentor.mentor.email }} - diff --git a/server/vbv_lernwelt/learning_mentor/tests/test_mentor.py b/server/vbv_lernwelt/learning_mentor/tests/test_mentor.py index 996d4dc7..88f83e68 100644 --- a/server/vbv_lernwelt/learning_mentor/tests/test_mentor.py +++ b/server/vbv_lernwelt/learning_mentor/tests/test_mentor.py @@ -285,7 +285,41 @@ class LearningMentorAPITest(APITestCase): self.assertEqual(mentor_user["email"], self.mentor.email) self.assertEqual(mentor_user["id"], str(self.mentor.id)) - def test_remove_user_mentor(self) -> None: + def test_remove_participant_as_mentor(self) -> None: + # GIVEN + self.client.force_login(self.mentor) + + participant_cs_user = add_course_session_user( + self.course_session, + create_user("participant"), + role=CourseSessionUser.Role.MEMBER, + ) + + learning_mentor = LearningMentor.objects.create( + mentor=self.mentor, course_session=self.course_session + ) + + learning_mentor.participants.add(participant_cs_user) + + remove_url = reverse( + "remove_participant_from_mentor", + kwargs={ + "course_session_id": self.course_session.id, + "mentor_id": learning_mentor.id, + "participant_user_id": participant_cs_user.user.id, + }, + ) + + # WHEN + response = self.client.delete(remove_url) + + # THEN + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertFalse( + LearningMentor.objects.filter(participants=participant_cs_user).exists() + ) + + def test_remove_myself_from_mentor(self) -> None: # GIVEN participant = create_user("participant") self.client.force_login(participant) @@ -302,16 +336,17 @@ class LearningMentorAPITest(APITestCase): learning_mentor.participants.add(participant_cs_user) - remove_self_url = reverse( - "remove_self_from_mentor", + remove_url = reverse( + "remove_participant_from_mentor", kwargs={ "course_session_id": self.course_session.id, "mentor_id": learning_mentor.id, + "participant_user_id": participant_cs_user.user.id, }, ) # WHEN - response = self.client.delete(remove_self_url) + response = self.client.delete(remove_url) # THEN self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) diff --git a/server/vbv_lernwelt/learning_mentor/urls.py b/server/vbv_lernwelt/learning_mentor/urls.py index c4c53f2f..b64ccd4e 100644 --- a/server/vbv_lernwelt/learning_mentor/urls.py +++ b/server/vbv_lernwelt/learning_mentor/urls.py @@ -6,9 +6,9 @@ urlpatterns = [ path("summary", views.mentor_summary, name="mentor_summary"), path("mentors", views.list_user_mentors, name="list_user_mentors"), path( - "mentors//leave", - views.remove_self_from_mentor, - name="remove_self_from_mentor", + "mentors//remove/", + views.remove_participant_from_mentor, + name="remove_participant_from_mentor", ), path("invitations", views.list_invitations, name="list_invitations"), path("invitations/create", views.create_invitation, name="create_invitation"), diff --git a/server/vbv_lernwelt/learning_mentor/views.py b/server/vbv_lernwelt/learning_mentor/views.py index d3b2c395..8ce99f2e 100644 --- a/server/vbv_lernwelt/learning_mentor/views.py +++ b/server/vbv_lernwelt/learning_mentor/views.py @@ -1,3 +1,4 @@ +import uuid from uuid import UUID from rest_framework import permissions, status @@ -79,7 +80,7 @@ def mentor_summary(request, course_session_id: int): ) -class CourseSessionMember(permissions.BasePermission): +class IsCourseSessionMember(permissions.BasePermission): def has_permission(self, request, view): return is_course_session_member( request.user, view.kwargs.get("course_session_id") @@ -87,7 +88,7 @@ class CourseSessionMember(permissions.BasePermission): @api_view(["GET"]) -@permission_classes([IsAuthenticated, CourseSessionMember]) +@permission_classes([IsAuthenticated, IsCourseSessionMember]) def list_invitations(request, course_session_id: int): course_session = get_object_or_404(CourseSession, id=course_session_id) course_session_user = get_object_or_404( @@ -99,7 +100,7 @@ def list_invitations(request, course_session_id: int): @api_view(["DELETE"]) -@permission_classes([IsAuthenticated, CourseSessionMember]) +@permission_classes([IsAuthenticated, IsCourseSessionMember]) def delete_invitation(request, course_session_id: int, invitation_id: UUID): course_session = get_object_or_404(CourseSession, id=course_session_id) course_session_user = get_object_or_404( @@ -113,7 +114,7 @@ def delete_invitation(request, course_session_id: int, invitation_id: UUID): @api_view(["POST"]) -@permission_classes([IsAuthenticated, CourseSessionMember]) +@permission_classes([IsAuthenticated, IsCourseSessionMember]) def create_invitation(request, course_session_id: int): user = request.user @@ -154,7 +155,7 @@ def create_invitation(request, course_session_id: int): @api_view(["GET"]) -@permission_classes([IsAuthenticated, CourseSessionMember]) +@permission_classes([IsAuthenticated, IsCourseSessionMember]) def list_user_mentors(request, course_session_id: int): course_session = get_object_or_404(CourseSession, id=course_session_id) @@ -170,14 +171,30 @@ def list_user_mentors(request, course_session_id: int): @api_view(["DELETE"]) -@permission_classes([IsAuthenticated, CourseSessionMember]) -def remove_self_from_mentor(request, course_session_id: int, mentor_id: int): - course_session = get_object_or_404(CourseSession, id=course_session_id) - course_session_user = get_object_or_404( - CourseSessionUser, user=request.user, course_session=course_session +@permission_classes([IsAuthenticated]) +def remove_participant_from_mentor( + request, course_session_id: int, mentor_id: int, participant_user_id: uuid.UUID +): + requester_user = request.user + mentor = get_object_or_404( + LearningMentor, id=mentor_id, course_session_id=course_session_id ) - mentor = get_object_or_404(LearningMentor, id=mentor_id) + is_requester_mentor = requester_user.id == mentor.mentor_id + is_requester_participant = mentor.participants.filter( + user=requester_user, course_session_id=course_session_id + ).exists() + + if not is_requester_mentor and not is_requester_participant: + return Response( + data={"message": "You are not allowed to remove participants"}, + status=status.HTTP_403_FORBIDDEN, + ) + + course_session = get_object_or_404(CourseSession, id=course_session_id) + course_session_user = get_object_or_404( + CourseSessionUser, user=participant_user_id, course_session=course_session + ) mentor.participants.remove(course_session_user)