From a6095cc5c4d968171e41d14877bd79bbe5b1c55f Mon Sep 17 00:00:00 2001 From: Danhia Date: Fri, 14 Jan 2022 23:41:59 +0100 Subject: [PATCH 1/3] removed 500 when user is not connected and want to access public event --- src/events/templatetags/is_flagged.py | 2 ++ src/events/views.py | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/events/templatetags/is_flagged.py b/src/events/templatetags/is_flagged.py index 0f50904..49d84e9 100644 --- a/src/events/templatetags/is_flagged.py +++ b/src/events/templatetags/is_flagged.py @@ -9,6 +9,8 @@ def isflagged(user, ctf): flagged = False event_info = ctf.event + if user.is_authenticated == False: + return "" if event_info.team_size == 1: if CTF_flags.objects.filter(user=user, ctf=ctf): flagged = True diff --git a/src/events/views.py b/src/events/views.py index 6857621..5a28310 100644 --- a/src/events/views.py +++ b/src/events/views.py @@ -222,10 +222,10 @@ def subscribe_to_event(request, event_slug): @login_required def create_team(request, event_slug): - response = redirect('events:create_team', event_slug=event_slug) + response = redirect('events:create_team', event_slug=event_slug) + ev = get_object_or_404(Event, slug=event_slug) if request.method == 'POST': - if request.user.is_authenticated: - ev = get_object_or_404(Event, slug=event_slug) + if request.user.is_authenticated and ev.team_size > 1: if Team.objects.filter(name=request.POST.get('teamname'), event=ev).exists(): return render(request, 'events/create_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'exist' : True}) new = Team(name=request.POST.get('teamname'), password=request.POST.get('password'), event=ev) @@ -237,10 +237,10 @@ def create_team(request, event_slug): @login_required def join_team(request, event_slug): - response = redirect('events:join_team', event_slug=event_slug) + response = redirect('events:join_team', event_slug=event_slug) + ev = get_object_or_404(Event, slug=event_slug) if request.method == 'POST': - if request.user.is_authenticated: - ev = get_object_or_404(Event, slug=event_slug) + if request.user.is_authenticated and ev.team_size > 1: try: team = Team.objects.get(name=request.POST.get('teamname'), event=ev) except: From 6a16e0fdbd5f9bf736fed7816d329a59a98775af Mon Sep 17 00:00:00 2001 From: Danhia Date: Sat, 15 Jan 2022 00:44:25 +0100 Subject: [PATCH 2/3] added auto matching for teams in event --- .../migrations/0006_auto_20220114_2319.py | 22 +++++++ src/events/models.py | 2 +- src/events/templates/events/create_team.html | 35 +++++----- src/events/templates/events/event_info.html | 4 +- src/events/templates/events/event_pwd.html | 4 +- src/events/templates/events/join_team.html | 64 +++++++++++++++++++ src/events/urls.py | 1 + src/events/utils.py | 10 +++ src/events/views.py | 36 +++++++++-- 9 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 src/events/migrations/0006_auto_20220114_2319.py create mode 100644 src/events/templates/events/join_team.html create mode 100644 src/events/utils.py diff --git a/src/events/migrations/0006_auto_20220114_2319.py b/src/events/migrations/0006_auto_20220114_2319.py new file mode 100644 index 0000000..ebc5023 --- /dev/null +++ b/src/events/migrations/0006_auto_20220114_2319.py @@ -0,0 +1,22 @@ +# Generated by Django 3.1.5 on 2022-01-14 23:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0005_auto_20211227_1556'), + ] + + operations = [ + migrations.RemoveField( + model_name='team', + name='size', + ), + migrations.AddField( + model_name='team', + name='auto', + field=models.BooleanField(default=False), + ), + ] diff --git a/src/events/models.py b/src/events/models.py index e6ff11e..57091bc 100644 --- a/src/events/models.py +++ b/src/events/models.py @@ -22,9 +22,9 @@ class Team(models.Model): name = models.CharField(max_length=200) password = models.CharField(max_length=200) event = models.ForeignKey(Event, on_delete=models.CASCADE, null=True) - size = models.PositiveIntegerField(default=1) score = models.PositiveIntegerField(default=0, db_index=True) last_submission_date = models.DateTimeField('Last Submission Date', default=timezone.now) + auto = models.BooleanField(default=False) def __str__(self): return self.name diff --git a/src/events/templates/events/create_team.html b/src/events/templates/events/create_team.html index 0e574ac..72e0ec6 100644 --- a/src/events/templates/events/create_team.html +++ b/src/events/templates/events/create_team.html @@ -10,17 +10,12 @@ {% endblock %} \ No newline at end of file diff --git a/src/events/templates/events/event_info.html b/src/events/templates/events/event_info.html index b6f8ec8..32c9542 100644 --- a/src/events/templates/events/event_info.html +++ b/src/events/templates/events/event_info.html @@ -108,8 +108,8 @@ {% endblock %} \ No newline at end of file diff --git a/src/events/templates/events/join_team.html b/src/events/templates/events/join_team.html index 2bfea69..005ac19 100644 --- a/src/events/templates/events/join_team.html +++ b/src/events/templates/events/join_team.html @@ -51,6 +51,7 @@ {% trans "Join Team" %} {% trans "Create Team" %} + {% if event.auto_match %} + {% endif %} {% endblock %} \ No newline at end of file diff --git a/src/events/utils.py b/src/events/utils.py index 274148d..69a9792 100644 --- a/src/events/utils.py +++ b/src/events/utils.py @@ -3,7 +3,7 @@ from random import choice, randint colors = ['blue', 'red', 'yellow', 'green', 'black', 'white', 'purple', 'orange', 'brown', 'fuchsia', 'gold', 'pink', 'cyan', 'magenta', 'pearl'] -animals = ['tiger', 'bee', 'dog', 'cat', 'otter', 'lizard', 'horse', 'mouse', 'butterfly', 'dolphin', 'elephant', 'falcon', 'goat' +animals = ['tiger', 'bee', 'dog', 'cat', 'otter', 'lizard', 'horse', 'mouse', 'butterfly', 'dolphin', 'elephant', 'falcon', 'goat', 'cow', 'lion', 'ostrich'] def get_random_name(): diff --git a/src/events/views/__init__.py b/src/events/views/__init__.py new file mode 100644 index 0000000..1c79547 --- /dev/null +++ b/src/events/views/__init__.py @@ -0,0 +1,2 @@ +from .events import * +from .teams import * \ No newline at end of file diff --git a/src/events/views.py b/src/events/views/events.py similarity index 60% rename from src/events/views.py rename to src/events/views/events.py index fb9edb8..7037a9e 100644 --- a/src/events/views.py +++ b/src/events/views/events.py @@ -1,16 +1,12 @@ from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import login_required from django.contrib.auth.models import timezone -from .forms import submit_flag, TeamUpdateForm -from .models import Event, EventPlayer, Team +from ..forms import submit_flag +from ..models import Event, EventPlayer, Team from ctfs.models import CTF, CTF_flags, Category from django.utils.translation import get_language from django.contrib.auth.models import User -from accounts.models import UserProfileInfo -from django.db.models import Q from django.utils.translation import gettext_lazy as _ -from .utils import get_random_name -from random import randint def get_description_by_lang(ctf): lang = get_language() @@ -222,47 +218,6 @@ def subscribe_to_event(request, event_slug): return render(request, 'events/create_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False}) return redirect('events:event_info', event_slug=event_slug) -@login_required -def create_team(request, event_slug): - response = redirect('events:create_team', event_slug=event_slug) - ev = get_object_or_404(Event, slug=event_slug) - if request.method == 'POST': - if request.user.is_authenticated and ev.team_size > 1: - if Team.objects.filter(name=request.POST.get('teamname'), event=ev).exists(): - return render(request, 'events/create_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'exist' : True}) - new = Team(name=request.POST.get('teamname'), password=request.POST.get('password'), event=ev) - new.save() - player = EventPlayer.objects.get(user=request.user, event=ev) - player.team = new - player.save() - return redirect('events:event_info', event_slug=event_slug) - -@login_required -def join_team(request, event_slug): - response = redirect('events:join_team', event_slug=event_slug) - ev = get_object_or_404(Event, slug=event_slug) - if request.method == 'POST': - if request.user.is_authenticated and ev.team_size > 1: - try: - team = Team.objects.get(name=request.POST.get('teamname'), event=ev) - except: - team = None - if team is None: - return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': True, 'registered' : True, 'notexist' : True}) - else: - members = EventPlayer.objects.filter(team=team) - if request.POST.get('password') != team.password: - return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': True, 'registered' : True, 'notexist' : False}) - if members.count() >= ev.team_size: - return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False, 'max' : True}) - else: - player = EventPlayer.objects.get(user=request.user, event=ev) - player.team = team - player.save() - else: - return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False}) - return redirect('events:event_info', event_slug=event_slug) - @login_required def profile(request, user_name, event_slug): catsDatas = [] @@ -302,125 +257,4 @@ def profile(request, user_name, event_slug): return render(request,'accounts/profile.html', {'user':user_obj, 'solves':solves,'solved':solved,'catsDatas': catsDatas, 'pointDatas': pointDatas, 'rank': rank, 'score' : somme, 'cats':cats}) -@login_required -def team_info(request, name, event_slug): - event_info = get_object_or_404(Event, slug=event_slug) - team = Team.objects.get(name=name, event=event_info) - catsDatas = [] - - players = EventPlayer.objects.filter(team=team, event=event_info) - users = [p.user for p in players] - all_teams = list(Team.objects.filter(event=event_info).order_by('-score', 'last_submission_date', 'name')) - rank = all_teams.index(get_object_or_404(Team, id=team.id, event=event_info)) + 1 - all_cats = Category.objects.all() - cats = [cat for cat in all_cats if CTF.objects.filter(category__name=cat.name, event=event_info)] - pointDatas = {} - - for cat in cats: - # prepare categories - solved_count = 0 - solved = [] - max_count = CTF.objects.filter(category__name=cat.name, event=event_info).count() - somme = 0 - pointDatas[cat.name] = [[event_info.start_date.timestamp()*1000, 0]] - for user_obj in users: - # get datas - solved_count += CTF_flags.objects.filter(user=user_obj, ctf__event=event_info , ctf__category__name=cat.name).count() - solved += CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name, ctf__event=event_info).order_by('flag_date') - percent = (solved_count / max_count) * 100 - catsDatas.append([cat.name, solved_count, max_count, '{:.0f}'.format(percent)]) - for flag in solved: - somme += flag.ctf.points - pointDatas[cat.name].append([flag.flag_date.timestamp() * 1000, somme]) - - query = Q() - for user_obj in users: - query |= Q(user=user_obj) - query &= Q(ctf__event=event_info) - - solves = CTF_flags.objects.filter(query).order_by('-flag_date') - solved = [] - somme = 0 - solved.append([event_info.start_date.timestamp() * 1000, 0]) - for s in solves.reverse(): - somme += s.ctf.points - solved.append([s.flag_date.timestamp() * 1000,somme]) - - return render(request,'events/team.html', {'users':users, 'solves':solves,'solved':solved,'catsDatas': catsDatas, 'pointDatas': pointDatas, - 'rank': rank, 'team':team, 'score':somme, 'event':event_info, 'cats':cats}) - -@login_required -def manage_team(request, event_slug): - event_info = get_object_or_404(Event, slug=event_slug) - player = EventPlayer.objects.get(user=request.user, event=event_info) - members = EventPlayer.objects.filter(team=player.team, event=event_info) - - if request.method == 'POST': - tname = player.team.name - p_form = TeamUpdateForm(request.POST, instance=player.team) - error = None - success = None - if p_form.is_valid(): - pname = p_form.cleaned_data['name'] - if pname == tname: - pass - else: - if Team.objects.filter(name=pname, event=event_info).exists(): - error = _("Name already taken.") - ppassword = p_form.cleaned_data['password'] - if error is None: - p_form.save() - success = _("Updated.") - - context={'p_form': p_form, 'error':error, 'success' : success, 'player':player, 'members':members} - return render(request, 'events/manage_team.html', context) - else: - p_form = TeamUpdateForm(instance=player.team) - context={'p_form': p_form, 'player':player, 'members':members} - return render(request, 'events/manage_team.html',context) - - -@login_required -def leave_team(request, event_slug): - event_info = get_object_or_404(Event, slug=event_slug) - player = EventPlayer.objects.get(user=request.user, event=event_info) - team = Team.objects.get(event=event_info, name=player.team.name) - - team.score -= player.score - team.save() - player.team = None - solved = CTF_flags.objects.filter(user=player.user, ctf__event=event_info) - player.score = 0 - solved.delete() - player.save() - - members = EventPlayer.objects.filter(team=team, event=event_info) - if members.count() == 0: - team.delete() - - return render(request, 'events/create_team.html', {'event' : event_info, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False}) - -@login_required -def find_team(request, event_slug): - event_info = get_object_or_404(Event, slug=event_slug) - teams = Team.objects.filter(event=event_info, auto=True) - team = None - player = EventPlayer.objects.get(user=request.user, event=event_info) - - for t in teams: - if EventPlayer.objects.filter(team=t, event=event_info).count() < event_info.team_size: - team = t - break - - if team is None: - teamname = get_random_name() - while Team.objects.filter(name=teamname, event=event_info).exists(): - teamname = get_random_name() - team = Team(name=teamname, password="".join([str(randint(0,10)) for _ in range(16)]), event=event_info, auto=True) - team.save() - - player.team = team - player.save() - - return redirect('events:event_info', event_slug=event_slug) diff --git a/src/events/views/teams.py b/src/events/views/teams.py new file mode 100644 index 0000000..af3e2a0 --- /dev/null +++ b/src/events/views/teams.py @@ -0,0 +1,176 @@ +from django.shortcuts import render, get_object_or_404, redirect +from django.contrib.auth.decorators import login_required +from ..forms import TeamUpdateForm +from ..models import Event, EventPlayer, Team +from ctfs.models import CTF, CTF_flags, Category +from django.contrib.auth.models import User +from django.db.models import Q +from django.utils.translation import gettext_lazy as _ +from ..utils import get_random_name +from random import randint + +@login_required +def create_team(request, event_slug): + response = redirect('events:create_team', event_slug=event_slug) + ev = get_object_or_404(Event, slug=event_slug) + if request.method == 'POST': + if request.user.is_authenticated and ev.team_size > 1: + if Team.objects.filter(name=request.POST.get('teamname'), event=ev).exists(): + return render(request, 'events/create_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'exist' : True}) + new = Team(name=request.POST.get('teamname'), password=request.POST.get('password'), event=ev) + new.save() + player = EventPlayer.objects.get(user=request.user, event=ev) + player.team = new + player.save() + return redirect('events:event_info', event_slug=event_slug) + +@login_required +def join_team(request, event_slug): + response = redirect('events:join_team', event_slug=event_slug) + ev = get_object_or_404(Event, slug=event_slug) + if request.method == 'POST': + if request.user.is_authenticated and ev.team_size > 1: + try: + team = Team.objects.get(name=request.POST.get('teamname'), event=ev) + except: + team = None + if team is None: + return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': True, 'registered' : True, 'notexist' : True}) + else: + members = EventPlayer.objects.filter(team=team) + if request.POST.get('password') != team.password: + return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': True, 'registered' : True, 'notexist' : False}) + if members.count() >= ev.team_size: + return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False, 'max' : True}) + else: + player = EventPlayer.objects.get(user=request.user, event=ev) + player.team = team + player.save() + else: + return render(request, 'events/join_team.html', {'event' : ev, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False}) + return redirect('events:event_info', event_slug=event_slug) + +@login_required +def team_info(request, name, event_slug): + event_info = get_object_or_404(Event, slug=event_slug) + team = Team.objects.get(name=name, event=event_info) + + catsDatas = [] + + players = EventPlayer.objects.filter(team=team, event=event_info) + users = [p.user for p in players] + all_teams = list(Team.objects.filter(event=event_info).order_by('-score', 'last_submission_date', 'name')) + rank = all_teams.index(get_object_or_404(Team, id=team.id, event=event_info)) + 1 + all_cats = Category.objects.all() + cats = [cat for cat in all_cats if CTF.objects.filter(category__name=cat.name, event=event_info)] + pointDatas = {} + + for cat in cats: + # prepare categories + solved_count = 0 + solved = [] + max_count = CTF.objects.filter(category__name=cat.name, event=event_info).count() + somme = 0 + pointDatas[cat.name] = [[event_info.start_date.timestamp()*1000, 0]] + for user_obj in users: + # get datas + solved_count += CTF_flags.objects.filter(user=user_obj, ctf__event=event_info , ctf__category__name=cat.name).count() + solved += CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name, ctf__event=event_info).order_by('flag_date') + percent = (solved_count / max_count) * 100 + catsDatas.append([cat.name, solved_count, max_count, '{:.0f}'.format(percent)]) + for flag in solved: + somme += flag.ctf.points + pointDatas[cat.name].append([flag.flag_date.timestamp() * 1000, somme]) + + query = Q() + for user_obj in users: + query |= Q(user=user_obj) + query &= Q(ctf__event=event_info) + + solves = CTF_flags.objects.filter(query).order_by('-flag_date') + solved = [] + somme = 0 + solved.append([event_info.start_date.timestamp() * 1000, 0]) + for s in solves.reverse(): + somme += s.ctf.points + solved.append([s.flag_date.timestamp() * 1000,somme]) + + return render(request,'events/team.html', {'users':users, 'solves':solves,'solved':solved,'catsDatas': catsDatas, 'pointDatas': pointDatas, + 'rank': rank, 'team':team, 'score':somme, 'event':event_info, 'cats':cats}) + +@login_required +def manage_team(request, event_slug): + event_info = get_object_or_404(Event, slug=event_slug) + player = EventPlayer.objects.get(user=request.user, event=event_info) + members = EventPlayer.objects.filter(team=player.team, event=event_info) + + if request.method == 'POST': + tname = player.team.name + p_form = TeamUpdateForm(request.POST, instance=player.team) + error = None + success = None + if p_form.is_valid(): + pname = p_form.cleaned_data['name'] + if pname == tname: + pass + else: + if Team.objects.filter(name=pname, event=event_info).exists(): + error = _("Name already taken.") + ppassword = p_form.cleaned_data['password'] + if error is None: + p_form.save() + success = _("Updated.") + + context={'p_form': p_form, 'error':error, 'success' : success, 'player':player, 'members':members} + return render(request, 'events/manage_team.html', context) + else: + p_form = TeamUpdateForm(instance=player.team) + context={'p_form': p_form, 'player':player, 'members':members} + return render(request, 'events/manage_team.html',context) + + +@login_required +def leave_team(request, event_slug): + event_info = get_object_or_404(Event, slug=event_slug) + player = EventPlayer.objects.get(user=request.user, event=event_info) + team = Team.objects.get(event=event_info, name=player.team.name) + + team.score -= player.score + team.save() + player.team = None + solved = CTF_flags.objects.filter(user=player.user, ctf__event=event_info) + player.score = 0 + solved.delete() + player.save() + + members = EventPlayer.objects.filter(team=team, event=event_info) + if members.count() == 0: + team.delete() + + return render(request, 'events/create_team.html', {'event' : event_info, 'logged': True, 'wrongpwd': False, 'registered' : True, 'notexist' : False}) + +@login_required +def find_team(request, event_slug): + event_info = get_object_or_404(Event, slug=event_slug) + teams = Team.objects.filter(event=event_info, auto=True) + team = None + player = EventPlayer.objects.get(user=request.user, event=event_info) + + if event_info.auto_match == False: + return redirect('events:event_info', event_slug=event_slug) + for t in teams: + if EventPlayer.objects.filter(team=t, event=event_info).count() < event_info.team_size: + team = t + break + + if team is None: + teamname = get_random_name() + while Team.objects.filter(name=teamname, event=event_info).exists(): + teamname = get_random_name() + team = Team(name=teamname, password="".join([str(randint(0,10)) for _ in range(16)]), event=event_info, auto=True) + team.save() + + player.team = team + player.save() + + return redirect('events:event_info', event_slug=event_slug) \ No newline at end of file