From 38d6664fa9fff25cd2a046703722f36b6da080c3 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 10 May 2023 14:50:04 +0500 Subject: [PATCH 1/7] collaborator can access a private competition. --- src/apps/api/views/competitions.py | 8 ++++++-- src/apps/competitions/views.py | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index ef90394a4..5c030f0ec 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -35,6 +35,7 @@ from leaderboards.models import Leaderboard from utils.data import make_url_sassy from api.permissions import IsOrganizerOrCollaborator +import logging; logger = logging.getLogger() class CompetitionViewSet(ModelViewSet): @@ -69,10 +70,11 @@ def get_queryset(self): ).values_list('status')[:1] qs = qs.annotate(participant_status=Subquery(participant_status_query)) - # new condition for search bar + # new condition # `mine` is true when this is called from "Benchmarks I'm Running" # `participating_in` is true when this is called from "Benchmarks I'm in" - # `mine` and `participating_in` are none when this is called from Search bar + # `mine` and `participating_in` are none when this is called either from Search bar + # or from competition detail page if (not mine) and (not participating_in): # User is logged in # filter his own competitions @@ -80,6 +82,7 @@ def get_queryset(self): # filter published competitions by other users qs = qs.filter( (Q(created_by=self.request.user)) | + (Q(collaborators__in=[self.request.user])) | (Q(published=True) & ~Q(created_by=self.request.user)) ) else: @@ -111,6 +114,7 @@ def get_queryset(self): ) search_query = self.request.query_params.get('search') + # search_query is true when called from searchbar if search_query: qs = qs.filter(Q(title__icontains=search_query) | Q(description__icontains=search_query)) diff --git a/src/apps/competitions/views.py b/src/apps/competitions/views.py index 581392fa1..61d09e0f3 100644 --- a/src/apps/competitions/views.py +++ b/src/apps/competitions/views.py @@ -28,13 +28,16 @@ class CompetitionDetail(DetailView): def get_object(self, *args, **kwargs): competition = super().get_object(*args, **kwargs) - is_creator, is_collaborator, is_participant = False, False, False + is_admin, is_creator, is_collaborator, is_participant = False, False, False, False # check if user is loggedin if self.request.user.is_authenticated: + # check if user is admin + is_admin = self.request.user.is_superuser + # check if user is the creator of this competition - is_creator = self.request.user.is_superuser or self.request.user == competition.created_by + is_creator = self.request.user == competition.created_by # check if user is collaborator of this competition is_collaborator = self.request.user in competition.collaborators.all() @@ -46,7 +49,14 @@ def get_object(self, *args, **kwargs): # check if secret key provided is valid valid_secret_key = self.request.GET.get('secret_key') == str(competition.secret_key) - if is_creator or is_collaborator or competition.published or valid_secret_key or is_participant: + if ( + is_admin or + is_creator or + is_collaborator or + competition.published or + valid_secret_key or + is_participant + ): return competition raise Http404() From 119b1dbe7c0354c5596a967715d2d6b68a1dd407 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 10 May 2023 14:53:37 +0500 Subject: [PATCH 2/7] removed unused import --- src/apps/api/views/competitions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index 5c030f0ec..eedbf7144 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -35,7 +35,6 @@ from leaderboards.models import Leaderboard from utils.data import make_url_sassy from api.permissions import IsOrganizerOrCollaborator -import logging; logger = logging.getLogger() class CompetitionViewSet(ModelViewSet): From 42b2e3bb7caa562f39ffdcc2077f99d3ae9f6962 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 10 May 2023 15:13:41 +0500 Subject: [PATCH 3/7] participant can not access a private competition --- src/apps/api/views/competitions.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index eedbf7144..36c61e608 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -75,13 +75,18 @@ def get_queryset(self): # `mine` and `participating_in` are none when this is called either from Search bar # or from competition detail page if (not mine) and (not participating_in): - # User is logged in - # filter his own competitions + # User is logged in then show + # compeitions which this user owns # or - # filter published competitions by other users + # compeititions in which this user is collaborator + # or + # competitions in which this user is participant and status is approved + # or + # compeitions is published and belongs to someone else qs = qs.filter( (Q(created_by=self.request.user)) | (Q(collaborators__in=[self.request.user])) | + (Q(participants__user=self.request.user, participants__status="approved")) | (Q(published=True) & ~Q(created_by=self.request.user)) ) else: From 509e4774c97715188532ab72a51857161dadd01f Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 10 May 2023 21:19:02 +0500 Subject: [PATCH 4/7] fixed the participants part of query --- src/apps/api/views/competitions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index 36c61e608..f252cd375 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -75,20 +75,20 @@ def get_queryset(self): # `mine` and `participating_in` are none when this is called either from Search bar # or from competition detail page if (not mine) and (not participating_in): - # User is logged in then show + # User is logged in then filter # compeitions which this user owns # or # compeititions in which this user is collaborator # or - # competitions in which this user is participant and status is approved - # or # compeitions is published and belongs to someone else qs = qs.filter( (Q(created_by=self.request.user)) | (Q(collaborators__in=[self.request.user])) | - (Q(participants__user=self.request.user, participants__status="approved")) | (Q(published=True) & ~Q(created_by=self.request.user)) ) + # or + # competitions in which this user is participant and status is approved + qs = qs.filter(participants__user=self.request.user, participants__status="approved") else: # if user is not authenticated only filter published/public competitions qs = qs.filter(Q(published=True)) From 4b689f67f3294082fce23378b28e22a7c32d2d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Pav=C3=A3o?= Date: Thu, 11 May 2023 16:12:17 +0200 Subject: [PATCH 5/7] Update competitions.py --- src/apps/api/views/competitions.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index f252cd375..d806466d1 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -69,7 +69,6 @@ def get_queryset(self): ).values_list('status')[:1] qs = qs.annotate(participant_status=Subquery(participant_status_query)) - # new condition # `mine` is true when this is called from "Benchmarks I'm Running" # `participating_in` is true when this is called from "Benchmarks I'm in" # `mine` and `participating_in` are none when this is called either from Search bar @@ -78,9 +77,9 @@ def get_queryset(self): # User is logged in then filter # compeitions which this user owns # or - # compeititions in which this user is collaborator + # competitions in which this user is collaborator # or - # compeitions is published and belongs to someone else + # competitions is published and belongs to someone else qs = qs.filter( (Q(created_by=self.request.user)) | (Q(collaborators__in=[self.request.user])) | From 547cd0e66fe1943cb6b7ccfe7183134a05160420 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Thu, 11 May 2023 19:30:52 +0500 Subject: [PATCH 6/7] participant condition fixed for private competition --- src/apps/api/views/competitions.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index f252cd375..56294277f 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -81,14 +81,14 @@ def get_queryset(self): # compeititions in which this user is collaborator # or # compeitions is published and belongs to someone else + # or + # competitions in which this user is participant and status is approved qs = qs.filter( (Q(created_by=self.request.user)) | (Q(collaborators__in=[self.request.user])) | - (Q(published=True) & ~Q(created_by=self.request.user)) - ) - # or - # competitions in which this user is participant and status is approved - qs = qs.filter(participants__user=self.request.user, participants__status="approved") + (Q(published=True) & ~Q(created_by=self.request.user)) | + (Q(participants__user=self.request.user) & Q(participants__status="approved")) + ).distinct() else: # if user is not authenticated only filter published/public competitions qs = qs.filter(Q(published=True)) From 92049ed3081150836663ba042e124986c9ae5be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Pav=C3=A3o?= Date: Thu, 11 May 2023 16:34:54 +0200 Subject: [PATCH 7/7] Update competitions.py (typos) --- src/apps/api/views/competitions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index 0e74f7970..541869c81 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -75,11 +75,11 @@ def get_queryset(self): # or from competition detail page if (not mine) and (not participating_in): # User is logged in then filter - # compeitions which this user owns + # competitions which this user owns # or # competitions in which this user is collaborator # or - # compeitions is published and belongs to someone else + # competitions is published and belongs to someone else # or # competitions in which this user is participant and status is approved qs = qs.filter(