Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 50 additions & 11 deletions src/apps/api/views/competitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,24 @@ class CompetitionViewSet(ModelViewSet):
permission_classes = (AllowAny,)

def get_queryset(self):

qs = super().get_queryset()

# filter by competition_type first, 'competition' by default
competition_type = self.request.query_params.get('type', Competition.COMPETITION)
if competition_type != 'any' and self.detail is False:
qs = qs.filter(competition_type=competition_type)

# Filter for search bar
search_query = self.request.query_params.get('search')

# Competition Secret key check
secret_key = self.request.query_params.get('secret_key')

# If user is logged in
if self.request.user.is_authenticated:
# filter by competition_type first, 'competition' by default
competition_type = self.request.query_params.get('type', Competition.COMPETITION)
if competition_type != 'any' and self.detail is False:
qs = qs.filter(competition_type=competition_type)

# `mine` is true when this is called from "Benchmarks I'm Running"
# Filter to only see competitions you own
mine = self.request.query_params.get('mine', None)
if mine:
Expand All @@ -65,19 +74,19 @@ def get_queryset(self):
(Q(collaborators__in=[self.request.user]))
).distinct()

# `participating_in` is true when this is called from "Benchmarks I'm in"
participating_in = self.request.query_params.get('participating_in', None)
if participating_in:
qs = qs.filter(participants__user=self.request.user, participants__status="approved")

participant_status_query = CompetitionParticipant.objects.filter(
competition=OuterRef('pk'),
user=self.request.user
).values_list('status')[:1]
qs = qs.annotate(participant_status=Subquery(participant_status_query))
# `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"
# `search_query` is true when this is called from the search bar

# if `search_query` is true, this is called form search bar
if search_query:
# User is logged in then filter
# competitions which this user owns
# or
# competitions in which this user is collaborator
Expand All @@ -91,10 +100,40 @@ def get_queryset(self):
(Q(published=True) & ~Q(created_by=self.request.user)) |
(Q(participants__user=self.request.user) & Q(participants__status="approved"))
).distinct()

# if `secret_key` is true, this is called for a secret competition
if secret_key:
print(secret_key)
qs = qs.filter(Q(secret_key=secret_key))

# Default condition
# not called from my competitions tab
# not called from i'm participating in tab
# not called from search bar
# not called with a valid secret key
# Return the following ---
# All competitions which belongs to you (private or public)
# And competitions where you are admin
# And public competitions
# And competitions where you are approved participant
# this filters out all private compettions from other users
if (not mine) and (not participating_in) and (not secret_key) and (not search_query):
qs = qs.filter(
(Q(created_by=self.request.user)) |
(Q(collaborators__in=[self.request.user])) |
(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 show public competitions in the search
if (search_query):
qs = qs.filter(Q(published=True))
# if user is not authenticated only show
# public competitions
# or
# competition with valid secret key
qs = qs.filter(
(Q(published=True)) |
(Q(secret_key=secret_key))
)

# On GETs lets optimize the query to reduce DB calls
if self.request.method == 'GET':
Expand Down
4 changes: 2 additions & 2 deletions src/apps/competitions/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
# path('', views.CompetitionList.as_view(), name="list"),
path('', views.CompetitionManagement.as_view(), name="management"),
path('<int:pk>/', views.CompetitionDetail.as_view(), name="detail"),
path('create/', views.CompetitionForm.as_view(), name="create"),
path('edit/<int:pk>/', views.CompetitionForm.as_view(), name="edit"),
path('create/', views.CompetitionCreateForm.as_view(), name="create"),
path('edit/<int:pk>/', views.CompetitionUpdateForm.as_view(), name="edit"),
path('upload/', views.CompetitionUpload.as_view(), name="upload"),
path('public/', views.CompetitionPublic.as_view(), name="public"),
path('<int:pk>/detailed_results/<int:submission_id>/', views.CompetitionDetailedResults.as_view(), name="detailed_results"),
Expand Down
43 changes: 42 additions & 1 deletion src/apps/competitions/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,40 @@ class CompetitionPublic(TemplateView):
template_name = 'competitions/public.html'


class CompetitionForm(LoginRequiredMixin, TemplateView):
class CompetitionCreateForm(LoginRequiredMixin, TemplateView):
template_name = 'competitions/form.html'


class CompetitionUpdateForm(LoginRequiredMixin, DetailView):
template_name = 'competitions/form.html'
queryset = Competition.objects.all()

def get_object(self, *args, **kwargs):
competition = super().get_object(*args, **kwargs)

is_admin, is_creator, is_collaborator = 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 == competition.created_by

# check if user is collaborator of this competition
is_collaborator = self.request.user in competition.collaborators.all()

if (
is_admin or
is_creator or
is_collaborator
):
return competition
raise Http404()


class CompetitionUpload(LoginRequiredMixin, TemplateView):
template_name = 'competitions/upload.html'

Expand Down Expand Up @@ -60,6 +90,17 @@ def get_object(self, *args, **kwargs):
return competition
raise Http404()

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)

# Retrieve the secret_key from the request.GET dictionary
secret_key = self.request.GET.get('secret_key')

# Add the secret_key to the context dictionary
context['secret_key'] = secret_key

return context


class CompetitionDetailedResults(LoginRequiredMixin, TemplateView):
template_name = 'competitions/detailed_results.html'
10 changes: 8 additions & 2 deletions src/static/js/ours/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ CODALAB.api = {
/*---------------------------------------------------------------------
Competitions
---------------------------------------------------------------------*/
get_competition: function (pk) {
return CODALAB.api.request('GET', URLS.API + "competitions/" + pk + "/")
get_competition: function (pk, secret_key) {

if(secret_key == undefined || secret_key == 'None'){
return CODALAB.api.request('GET', URLS.API + "competitions/" + pk + "/")
}else{
return CODALAB.api.request('GET', URLS.API + "competitions/" + pk + "/?secret_key="+secret_key)
}

},
get_competitions: function (query) {
return CODALAB.api.request('GET', URLS.API + "competitions/", query)
Expand Down
2 changes: 1 addition & 1 deletion src/static/riot/competitions/detail/detail.tag
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
})

self.update_competition_data = function () {
CODALAB.api.get_competition(self.opts.competition_pk)
CODALAB.api.get_competition(self.opts.competition_pk, self.opts.secret_key)
.done(function (data) {
self.competition = data
CODALAB.events.trigger('competition_loaded', self.competition)
Expand Down
2 changes: 1 addition & 1 deletion src/templates/competitions/detail.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "base.html" %}
{% block content %}
<competition-detail competition_pk="{{ object.pk }}"></competition-detail>
<competition-detail competition_pk="{{ object.pk }}" secret_key="{{ secret_key }}"></competition-detail>
{% endblock %}
2 changes: 1 addition & 1 deletion src/templates/competitions/form.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% extends "base.html" %}

{% block content %}
<competition-form competition_id="{{ pk }}">
<competition-form competition_id="{{ object.pk }}">
</competition-form>

{# NOTE: First added for phase task sorting, SemanticUI does not come with sorting..! #}
Expand Down