Skip to content

Commit aff8314

Browse files
authored
Merge pull request #2155 from codalab/public-detailed-results
Make detailed results public when competition is public
2 parents 716f8e6 + 1ac0db7 commit aff8314

3 files changed

Lines changed: 89 additions & 34 deletions

File tree

src/apps/api/tests/test_submissions.py

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,16 @@ def test_no_one_can_see_detailed_result_when_visualization_is_false(self):
243243
resp = self.client.get(url)
244244
assert resp.status_code == 404
245245

246-
def test_who_can_see_detailed_result_when_visualization_is_true(self):
246+
def test_who_can_see_detailed_result_when_visualization_is_true_and_competition_is_private(self):
247247
self.comp.enable_detailed_results = True
248+
self.comp.published = False
248249
self.comp.save()
249-
url = reverse('submission-get-detail-result', args=(self.existing_submission.pk,))
250+
251+
url = reverse("submission-get-detail-result", args=(self.existing_submission.pk,))
252+
253+
# Anonymous user cannot see submission detail result
254+
resp = self.client.get(url)
255+
assert resp.status_code == 403
250256

251257
# Competition creator can see detail result
252258
self.client.force_login(self.creator)
@@ -263,17 +269,17 @@ def test_who_can_see_detailed_result_when_visualization_is_true(self):
263269
resp = self.client.get(url)
264270
assert resp.status_code == 200
265271

266-
# approved user can see submission detail result
272+
# Approved user can see submission detail result
267273
self.client.force_login(self.participant)
268274
resp = self.client.get(url)
269275
assert resp.status_code == 200
270276

271-
# pending user cannot see submission detail result
277+
# Pending user cannot see submission detail result
272278
self.client.force_login(self.pending_participant)
273279
resp = self.client.get(url)
274280
assert resp.status_code == 403
275281

276-
# denied user cannot see submission detail result
282+
# Denied user cannot see submission detail result
277283
self.client.force_login(self.denied_participant)
278284
resp = self.client.get(url)
279285
assert resp.status_code == 403
@@ -283,6 +289,45 @@ def test_who_can_see_detailed_result_when_visualization_is_true(self):
283289
resp = self.client.get(url)
284290
assert resp.status_code == 403
285291

292+
def test_who_can_see_detailed_result_when_visualization_is_true_and_competition_is_public(self):
293+
self.comp.enable_detailed_results = True
294+
self.comp.published = True
295+
self.comp.save()
296+
297+
url = reverse("submission-get-detail-result", args=(self.existing_submission.pk,))
298+
299+
# Detailed results are publicly available
300+
resp = self.client.get(url)
301+
assert resp.status_code == 200
302+
303+
self.client.force_login(self.creator)
304+
resp = self.client.get(url)
305+
assert resp.status_code == 200
306+
307+
self.client.force_login(self.collaborator)
308+
resp = self.client.get(url)
309+
assert resp.status_code == 200
310+
311+
self.client.force_login(self.superuser)
312+
resp = self.client.get(url)
313+
assert resp.status_code == 200
314+
315+
self.client.force_login(self.participant)
316+
resp = self.client.get(url)
317+
assert resp.status_code == 200
318+
319+
self.client.force_login(self.pending_participant)
320+
resp = self.client.get(url)
321+
assert resp.status_code == 200
322+
323+
self.client.force_login(self.denied_participant)
324+
resp = self.client.get(url)
325+
assert resp.status_code == 200
326+
327+
self.client.force_login(self.other_user)
328+
resp = self.client.get(url)
329+
assert resp.status_code == 200
330+
286331

287332
class SubmissionUpdateTest(APITestCase):
288333
def setUp(self):

src/apps/api/views/submissions.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -482,37 +482,47 @@ def get_details(self, request, pk):
482482

483483
@action(detail=True, methods=('GET',))
484484
def get_detail_result(self, request, pk):
485-
submission = Submission.objects.get(pk=pk)
486-
# Check if competition show visualization is true
487-
if submission.phase.competition.enable_detailed_results:
488-
# get submission's competition approved participants
489-
approved_participants = submission.phase.competition.participants.filter(status=CompetitionParticipant.APPROVED)
490-
participant_usernames = [participant.user.username for participant in approved_participants]
491-
492-
# check if in this competition
493-
# user is collaborator
494-
# or
495-
# user is approved participant
496-
# or
497-
# user is creator
498-
# or
499-
# user is super user
500-
if request.user in submission.phase.competition.collaborators.all() or\
501-
request.user.username in participant_usernames or\
502-
request.user == submission.phase.competition.created_by or\
503-
request.user.is_superuser:
504-
505-
data = SubmissionFilesSerializer(submission, context=self.get_serializer_context()).data
506-
return Response(data["detailed_result"], status=status.HTTP_200_OK)
485+
submission = get_object_or_404(Submission, pk=pk)
486+
competition = submission.phase.competition
507487

488+
# Helper to avoid repeating serialization/Response code
489+
def _allowed():
490+
data = SubmissionFilesSerializer(submission, context=self.get_serializer_context()).data
491+
return Response(data.get("detailed_result"), status=status.HTTP_200_OK)
492+
493+
# Check if competition show visualization is true
494+
if competition.enable_detailed_results:
495+
if competition.published:
496+
# Detailed results are publicly available
497+
return _allowed()
508498
else:
509-
return Response({
510-
"error_msg": "You do not have permission to see the detailed result. Participate in this competition to view result."},
511-
status=status.HTTP_403_FORBIDDEN
512-
)
499+
# Competition is private
500+
user = request.user
501+
if not user.is_authenticated:
502+
return Response(
503+
{"error_msg": "You do not have permission to see the detailed result. Participate in this competition to view result."},
504+
status=status.HTTP_403_FORBIDDEN,
505+
)
506+
# Give access if user is collaborator, approved participant,
507+
# competition creator or super user
508+
is_collaborator = competition.collaborators.filter(pk=user.pk).exists()
509+
is_creator = (user == competition.created_by)
510+
is_superuser = user.is_superuser
511+
is_approved_participant = CompetitionParticipant.objects.filter(
512+
competition=competition,
513+
user=user,
514+
status=CompetitionParticipant.APPROVED,
515+
).exists()
516+
if is_collaborator or is_approved_participant or is_creator or is_superuser:
517+
# Allow access
518+
return _allowed()
519+
return Response(
520+
{"error_msg": "You do not have permission to see the detailed result."},
521+
status=status.HTTP_403_FORBIDDEN,
522+
)
513523
else:
514-
return Response({
515-
"error_msg": "Detailed results are disable for this competition!"},
524+
return Response(
525+
{"error_msg": "Detailed results are disabled for this competition!"},
516526
status=status.HTTP_404_NOT_FOUND
517527
)
518528

src/apps/competitions/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,5 @@ def get_context_data(self, **kwargs):
102102
return context
103103

104104

105-
class CompetitionDetailedResults(LoginRequiredMixin, TemplateView):
105+
class CompetitionDetailedResults(TemplateView):
106106
template_name = 'competitions/detailed_results.html'

0 commit comments

Comments
 (0)