Repository: Cloud-CV/EvalAI

Issue:
Improve the check for if the user is a host of a challenge
Currently, at https://github.com/Cloud-CV/EvalAI/blob/master/apps/hosts/utils.py#L12 we only check if the user has created the challegne and based on that we allow the challenge host to see all the submissions (for example, see this https://github.com/Cloud-CV/EvalAI/blob/master/apps/challenges/views.py#L703). We would want to change it so that anyone who is a part of the challenge host team is allowed to access information such as 'View all submissions' etc. 


Discussion:

Resolving patch:
diff --git a/apps/participants/urls.py b/apps/participants/urls.py
--- a/apps/participants/urls.py
+++ b/apps/participants/urls.py
@@ -10,7 +10,7 @@
         name='remove_self_from_participant_team'),
     url(r'participant_team/(?P<participant_team_pk>[0-9]+)/participant/(?P<participant_pk>[0-9]+)$',
         views.delete_participant_from_team, name='delete_participant_from_team'),
-    url(r'participant_teams/challenges/user',
+    url(r'participant_teams/challenges/(?P<challenge_pk>[0-9]+)/user$',
         views.get_teams_and_corresponding_challenges_for_a_participant,
         name='get_teams_and_corresponding_challenges_for_a_participant'),
     url(r'participant_team$', views.participant_team_list,
diff --git a/apps/participants/views.py b/apps/participants/views.py
--- a/apps/participants/views.py
+++ b/apps/participants/views.py
@@ -13,6 +13,7 @@
 from accounts.permissions import HasVerifiedEmail
 from base.utils import paginated_queryset
 from challenges.models import Challenge
+from hosts.utils import is_user_a_host_of_challenge
 
 from .models import (Participant, ParticipantTeam)
 from .serializers import (InviteParticipantToTeamSerializer,
@@ -178,13 +179,15 @@ def delete_participant_from_team(request, participant_team_pk, participant_pk):
 @api_view(['GET', ])
 @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail))
 @authentication_classes((ExpiringTokenAuthentication,))
-def get_teams_and_corresponding_challenges_for_a_participant(request):
+def get_teams_and_corresponding_challenges_for_a_participant(request, challenge_pk):
     """
     Returns list of teams and corresponding challenges for a participant
     """
     # first get list of all the participants and teams related to the user
     participant_objs = Participant.objects.filter(user=request.user).prefetch_related('team')
 
+    is_challenge_host = is_user_a_host_of_challenge(user=request.user, challenge_pk=challenge_pk)
+
     challenge_participated_teams = []
     for participant_obj in participant_objs:
         participant_team = participant_obj.team
@@ -201,7 +204,9 @@ def get_teams_and_corresponding_challenges_for_a_participant(request):
             challenge_participated_teams.append(ChallengeParticipantTeam(
                 challenge, participant_team))
     serializer = ChallengeParticipantTeamListSerializer(ChallengeParticipantTeamList(challenge_participated_teams))
-    return Response(serializer.data, status=status.HTTP_200_OK)
+    response_data = serializer.data
+    response_data['is_challenge_host'] = is_challenge_host
+    return Response(response_data, status=status.HTTP_200_OK)
 
 
 @throttle_classes([UserRateThrottle])


Test patch:
diff --git a/tests/unit/participants/test_urls.py b/tests/unit/participants/test_urls.py
--- a/tests/unit/participants/test_urls.py
+++ b/tests/unit/participants/test_urls.py
@@ -108,9 +108,10 @@ def test_delete_participant_from_team_url(self):
 
     def test_get_teams_and_corresponding_challenges_for_a_participant_url(self):
         self.url = reverse_lazy(
-            'participants:get_teams_and_corresponding_challenges_for_a_participant')
+            'participants:get_teams_and_corresponding_challenges_for_a_participant',
+            kwargs={'challenge_pk': self.challenge.pk})
         self.assertEqual(
-            unicode(self.url), '/api/participants/participant_teams/challenges/user')
+            unicode(self.url), '/api/participants/participant_teams/challenges/{}/user'.format(self.challenge.pk))
         resolver = resolve(self.url)
         self.assertEqual(
             resolver.view_name, 'participants:get_teams_and_corresponding_challenges_for_a_participant')
diff --git a/tests/unit/participants/test_views.py b/tests/unit/participants/test_views.py
--- a/tests/unit/participants/test_views.py
+++ b/tests/unit/participants/test_views.py
@@ -503,9 +503,6 @@ class GetTeamsAndCorrespondingChallengesForAParticipant(BaseAPITestClass):
     def setUp(self):
         super(GetTeamsAndCorrespondingChallengesForAParticipant, self).setUp()
 
-        self.url = reverse_lazy(
-            'participants:get_teams_and_corresponding_challenges_for_a_participant',)
-
         self.user2 = User.objects.create(
             username='user2',
             email='user2@platform.com',
@@ -567,6 +564,10 @@ def setUp(self):
             end_date=timezone.now() + timedelta(days=1),
             )
 
+        self.url = reverse_lazy(
+            'participants:get_teams_and_corresponding_challenges_for_a_participant',
+            kwargs={'challenge_pk': self.challenge1.pk})
+
     def test_get_teams_and_corresponding_challenges_for_a_participant(self):
 
         self.challenge1.participant_teams.add(self.participant_team1)
@@ -603,7 +604,8 @@ def test_get_teams_and_corresponding_challenges_for_a_participant(self):
                         "created_by": self.participant_team1.created_by.username
                     }
                 }
-            ]
+            ],
+            "is_challenge_host": False
         }
         response = self.client.get(self.url, {})
         self.assertEqual(response.data, expected)
@@ -621,7 +623,8 @@ def test_when_participant_team_hasnot_participated_in_any_challenge(self):
                         "created_by": self.participant_team1.created_by.username
                     }
                 }
-            ]
+            ],
+            "is_challenge_host": False
         }
         response = self.client.get(self.url, {})
         self.assertEqual(response.data, expected)
@@ -632,7 +635,8 @@ def test_when_there_is_no_participant_team_of_user(self):
         self.participant_team1.delete()
 
         expected = {
-            "challenge_participant_team_list": []
+            "challenge_participant_team_list": [],
+            "is_challenge_host": False
         }
 
         response = self.client.get(self.url, {})