From 06dc8188a0f8138c4b084f6ceabc279c7a26b53c Mon Sep 17 00:00:00 2001 From: ix <0x00fi@protonmail.com> Date: Thu, 21 Oct 2021 15:02:02 +0200 Subject: [PATCH] events added, need to smooth html and css --- src/accounts/admin.py | 9 +- src/accounts/views/views.py | 8 +- src/ctfs/admin.py | 21 ++- src/ctfs/migrations/0005_ctf_event.py | 20 +++ src/ctfs/migrations/0006_alter_ctf_event.py | 20 +++ src/ctfs/models.py | 4 +- src/ctfs/templates/ctfs/ctf_info.html | 108 ++++++------- src/ctfs/views.py | 22 +-- src/events/__init__.py | 0 src/events/admin.py | 23 +++ src/events/apps.py | 6 + src/events/forms.py | 4 + src/events/migrations/0001_initial.py | 46 ++++++ .../migrations/0002_alter_event_password.py | 18 +++ .../migrations/0003_auto_20211019_1519.py | 26 ++++ src/events/migrations/__init__.py | 0 src/events/models.py | 26 ++++ src/events/templates/events/ctf_info.html | 87 +++++++++++ src/events/templates/events/event_info.html | 96 ++++++++++++ src/events/templates/events/event_pwd.html | 37 +++++ src/events/templates/events/events_list.html | 47 ++++++ src/events/templatetags/__init__.py | 0 src/events/templatetags/is_flagged.py | 10 ++ src/events/tests.py | 3 + src/events/urls.py | 13 ++ src/events/views.py | 143 ++++++++++++++++++ src/home/views.py | 2 +- src/project/settings.py | 1 + src/project/urls.py | 3 +- .../templates/scoreboard/scoreboard.html | 62 ++++---- src/static/css/style.css | 2 +- src/statics/css/style.css | 22 ++- src/templates/base.html | 143 +++++++++--------- 33 files changed, 851 insertions(+), 181 deletions(-) create mode 100644 src/ctfs/migrations/0005_ctf_event.py create mode 100644 src/ctfs/migrations/0006_alter_ctf_event.py create mode 100644 src/events/__init__.py create mode 100644 src/events/admin.py create mode 100644 src/events/apps.py create mode 100644 src/events/forms.py create mode 100644 src/events/migrations/0001_initial.py create mode 100644 src/events/migrations/0002_alter_event_password.py create mode 100644 src/events/migrations/0003_auto_20211019_1519.py create mode 100644 src/events/migrations/__init__.py create mode 100644 src/events/models.py create mode 100644 src/events/templates/events/ctf_info.html create mode 100644 src/events/templates/events/event_info.html create mode 100644 src/events/templates/events/event_pwd.html create mode 100755 src/events/templates/events/events_list.html create mode 100644 src/events/templatetags/__init__.py create mode 100644 src/events/templatetags/is_flagged.py create mode 100644 src/events/tests.py create mode 100644 src/events/urls.py create mode 100644 src/events/views.py diff --git a/src/accounts/admin.py b/src/accounts/admin.py index 930ef46..e1fbd9b 100644 --- a/src/accounts/admin.py +++ b/src/accounts/admin.py @@ -1,5 +1,12 @@ from .models import UserProfileInfo from django.contrib import admin -admin.site.register(UserProfileInfo) +#admin.site.register(UserProfileInfo) # Register your models here. + +@admin.register(UserProfileInfo) +class userprofile(admin.ModelAdmin): + #list display + list_display = ['user', 'score', 'last_submission_date'] + # search list + search_fields = ['score', 'user__username'] \ No newline at end of file diff --git a/src/accounts/views/views.py b/src/accounts/views/views.py index 9ad51bf..af6cde5 100644 --- a/src/accounts/views/views.py +++ b/src/accounts/views/views.py @@ -121,11 +121,11 @@ def profile(request, user_name): for cat in cats: # prepare categories - solved_count = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name).count() - max_count = CTF.objects.filter(category__name=cat.name).count() + solved_count = CTF_flags.objects.filter(user=user_obj, ctf__event=None , ctf__category__name=cat.name).count() + max_count = CTF.objects.filter(category__name=cat.name, event=None).count() # get datas somme = 0 - solved = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name).order_by('flag_date') + solved = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name, ctf__event=None).order_by('flag_date') pointDatas[cat.name] = [] pointDatas[cat.name].append([user_obj.date_joined.timestamp() * 1000, 0]) percent = (solved_count / max_count) * 100 @@ -134,7 +134,7 @@ def profile(request, user_name): somme += flag.ctf.points pointDatas[cat.name].append([flag.flag_date.timestamp() * 1000, somme]) - solves = CTF_flags.objects.filter(user=user_obj).order_by('-flag_date') + solves = CTF_flags.objects.filter(user=user_obj, ctf__event=None).order_by('-flag_date') solved = [] somme = 0 solved.append([user_obj.date_joined.timestamp() * 1000, 0]) diff --git a/src/ctfs/admin.py b/src/ctfs/admin.py index 83af521..c563116 100644 --- a/src/ctfs/admin.py +++ b/src/ctfs/admin.py @@ -2,7 +2,24 @@ from django.contrib import admin from .models import Category, CTF, CTF_flags admin.site.register(Category) -admin.site.register(CTF) -admin.site.register(CTF_flags) +#admin.site.register(CTF) +#admin.site.register(CTF_flags) +@admin.register(CTF_flags) +class ctf_flags(admin.ModelAdmin): + #list display + list_display = ['user', 'ctf', 'flag_date'] + #list Filter + list_filter = ('ctf__category', 'ctf', 'user','flag_date') + # search list + search_fields = ['ctf__category__name', 'ctf__name', 'user__username'] + +@admin.register(CTF) +class ctf(admin.ModelAdmin): + #list display + list_display = ['name', 'event', 'category'] + #list Filter + list_filter = ('category', 'event') + # search list + search_fields = ['category__name', 'name', 'author__username'] # Register your models here. diff --git a/src/ctfs/migrations/0005_ctf_event.py b/src/ctfs/migrations/0005_ctf_event.py new file mode 100644 index 0000000..5dd4c8b --- /dev/null +++ b/src/ctfs/migrations/0005_ctf_event.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.7 on 2021-10-18 14:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0001_initial'), + ('ctfs', '0004_auto_20210907_1407'), + ] + + operations = [ + migrations.AddField( + model_name='ctf', + name='event', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='events.event'), + ), + ] diff --git a/src/ctfs/migrations/0006_alter_ctf_event.py b/src/ctfs/migrations/0006_alter_ctf_event.py new file mode 100644 index 0000000..5651dda --- /dev/null +++ b/src/ctfs/migrations/0006_alter_ctf_event.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.7 on 2021-10-19 15:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0002_alter_event_password'), + ('ctfs', '0005_ctf_event'), + ] + + operations = [ + migrations.AlterField( + model_name='ctf', + name='event', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='events.event'), + ), + ] diff --git a/src/ctfs/models.py b/src/ctfs/models.py index 4958f77..6f49ca7 100644 --- a/src/ctfs/models.py +++ b/src/ctfs/models.py @@ -1,5 +1,6 @@ from django.db import models from django.contrib.auth.models import User +from events.models import Event class Category(models.Model): name = models.CharField(max_length=200) @@ -17,6 +18,7 @@ class CTF(models.Model): description_de = models.TextField(blank=True) file = models.FileField(blank=True, upload_to='challenges') ctf_url = models.URLField(blank=True) + event = models.ForeignKey(Event, null=True, blank=True, on_delete=models.CASCADE) points = models.PositiveSmallIntegerField() slug = models.SlugField(max_length=55) pub_date = models.DateTimeField('Date published') @@ -25,7 +27,7 @@ class CTF(models.Model): on_delete=models.SET_NULL, null=True, ) - author = models.ForeignKey(User, unique=False, on_delete=models.CASCADE) + author = models.ForeignKey(User, unique=False, on_delete=models.CASCADE) def solved_by(self, user): """True if the exercise has been solved by the user.""" if not user.is_authenticated: diff --git a/src/ctfs/templates/ctfs/ctf_info.html b/src/ctfs/templates/ctfs/ctf_info.html index 4d08e8b..228d7a1 100644 --- a/src/ctfs/templates/ctfs/ctf_info.html +++ b/src/ctfs/templates/ctfs/ctf_info.html @@ -6,79 +6,79 @@

{{ ctf.name }}

- {% trans "Published date" %} : {{ ctf.pub_date }} + {% trans "Published date" %} : {{ ctf.pub_date }}
- {% if description %} - {{ description|safe }} - {% else %} - {% trans "No translation available. Please try another language (English or French)." %} - {% endif %} + {% if description %} + {{ description|safe }} + {% else %} + {% trans "No translation available. Please try another language (English or French)." %} + {% endif %}
-

{% trans "Solved by" %}

- {% if solved_list %} - +

{% trans "Solved by" %}

+ {% if solved_list %} +
- - - - + + + + - {% for s in solved_list %} - - - - - + {% for s in solved_list %} + + + + + - {% endfor %} + {% endfor %}
{% trans "Username" %}{% trans "Website" %}{% trans "Score" %}{% trans "Date" %}{% trans "Username" %}{% trans "Website" %}{% trans "Score" %}{% trans "Date" %}
{{ s.user.username }}{{ s.user.userprofileinfo.portfolio_site }}{{ s.user.userprofileinfo.score }}{{ s.flag_date }}
{{ s.user.username }}{{ s.user.userprofileinfo.portfolio_site }}{{ s.user.userprofileinfo.score }}{{ s.flag_date }}
- {% else %} -

{% trans "Nobody have solved this CTF." %}

- {% endif %} + {% else %} +

{% trans "Nobody have solved this CTF." %}

+ {% endif %}
{% endblock %} diff --git a/src/ctfs/views.py b/src/ctfs/views.py index 0b0c1b3..7f15c08 100644 --- a/src/ctfs/views.py +++ b/src/ctfs/views.py @@ -21,10 +21,10 @@ def get_description_by_lang(ctf): def category(request, cat_slug): cat = get_object_or_404(Category, slug=cat_slug) - ctfs = CTF.objects.filter(category=cat).order_by('points') + ctfs = CTF.objects.filter(category=cat, event=None).order_by('points') for ex in ctfs: - ex.solved_num = CTF_flags.objects.filter(ctf=ex).count() - ex.solved = ex.solved_by(request.user) + ex.solved_num = CTF_flags.objects.filter(ctf=ex).count() + ex.solved = ex.solved_by(request.user) return render(request, 'ctfs/ctfs_list.html', {'ctfs' : ctfs, 'cat' : cat}) def ctf(request, cat_slug, ctf_slug): @@ -46,18 +46,12 @@ def ctf(request, cat_slug, ctf_slug): profil.last_submission_date = timezone.now() profil.score += ctf_info.points profil.save() - return render(request, 'ctfs/ctf_info.html', {'form' : form, 'ctf' : ctf_info, 'solved_list': solved_list, 'valitated': True, 'description': description}) + return render(request, 'ctfs/ctf_info.html', { 'ctf' : ctf_info, 'solved_list': solved_list, 'valitated': True, 'description': description}) else: - return render(request, 'ctfs/ctf_info.html', {'form' : form, 'ctf' : ctf_info, 'solved_list': solved_list, 'failed': True, 'description': description}) + return render(request, 'ctfs/ctf_info.html', { 'ctf' : ctf_info, 'solved_list': solved_list, 'failed': True, 'description': description}) else: - form = submit_flag() - return render(request, 'ctfs/ctf_info.html', {'form' : form, 'ctf' : ctf_info, 'solved_list': solved_list, 'alvalitated': True, 'description': description}) + return render(request, 'ctfs/ctf_info.html', { 'ctf' : ctf_info, 'solved_list': solved_list, 'alvalitated': True, 'description': description}) else: - form = submit_flag() - return render(request, 'ctfs/ctf_info.html', {'form' : form, 'ctf' : ctf_info, 'solved_list': solved_list, 'description': description}) + return render(request, 'ctfs/ctf_info.html', { 'ctf' : ctf_info, 'solved_list': solved_list, 'description': description}) else: - form = submit_flag() - return render(request, 'ctfs/ctf_info.html', {'form' : form, 'ctf' : ctf_info, 'solved_list': solved_list, 'alvalitated': flagged, 'description': description}) - - -# Create your views here. + return render(request, 'ctfs/ctf_info.html', { 'ctf' : ctf_info, 'solved_list': solved_list, 'alvalitated': flagged, 'description': description}) diff --git a/src/events/__init__.py b/src/events/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/events/admin.py b/src/events/admin.py new file mode 100644 index 0000000..77ae37b --- /dev/null +++ b/src/events/admin.py @@ -0,0 +1,23 @@ +from django.contrib import admin +from .models import Event, Scores + +#admin.site.register(Event) +#admin.site.register(Scores) + +@admin.register(Event) +class event(admin.ModelAdmin): + #list display + list_display = ['name', 'start_date', 'end_date'] + # search list + search_fields = ['name', 'slug', 'description', 'password'] + +@admin.register(Scores) +class score(admin.ModelAdmin): + #list display + list_display = ['user', 'event', 'score'] + #list Filter + list_filter = ('event',) + # search list + search_fields = ['user__username', 'score', 'event__name'] + +# Register your models here. diff --git a/src/events/apps.py b/src/events/apps.py new file mode 100644 index 0000000..20f48f2 --- /dev/null +++ b/src/events/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class EventsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'events' diff --git a/src/events/forms.py b/src/events/forms.py new file mode 100644 index 0000000..acdc47e --- /dev/null +++ b/src/events/forms.py @@ -0,0 +1,4 @@ +from django import forms + +class submit_flag(forms.Form): + flag = forms.CharField(label="Flag", max_length=100) diff --git a/src/events/migrations/0001_initial.py b/src/events/migrations/0001_initial.py new file mode 100644 index 0000000..84126c6 --- /dev/null +++ b/src/events/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# Generated by Django 3.2.7 on 2021-10-18 14:19 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=200)), + ('logo', models.CharField(max_length=200)), + ('img', models.CharField(max_length=200)), + ('description', models.TextField()), + ('start_date', models.DateTimeField()), + ('end_date', models.DateTimeField()), + ('password', models.CharField(max_length=200)), + ('slug', models.SlugField(max_length=55)), + ], + ), + migrations.CreateModel( + name='Scores', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('score', models.PositiveIntegerField(db_index=True, default=0)), + ('last_submission_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Last Submission Date')), + ('event', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='events.event')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-score', 'last_submission_date', 'user__username'], + }, + ), + ] diff --git a/src/events/migrations/0002_alter_event_password.py b/src/events/migrations/0002_alter_event_password.py new file mode 100644 index 0000000..3216874 --- /dev/null +++ b/src/events/migrations/0002_alter_event_password.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.7 on 2021-10-18 14:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='event', + name='password', + field=models.CharField(blank=True, max_length=200), + ), + ] diff --git a/src/events/migrations/0003_auto_20211019_1519.py b/src/events/migrations/0003_auto_20211019_1519.py new file mode 100644 index 0000000..3ee71f7 --- /dev/null +++ b/src/events/migrations/0003_auto_20211019_1519.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.7 on 2021-10-19 15:19 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('events', '0002_alter_event_password'), + ] + + operations = [ + migrations.AlterField( + model_name='scores', + name='event', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.event'), + ), + migrations.AlterField( + model_name='scores', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/src/events/migrations/__init__.py b/src/events/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/events/models.py b/src/events/models.py new file mode 100644 index 0000000..ea8edea --- /dev/null +++ b/src/events/models.py @@ -0,0 +1,26 @@ +from django.db import models +from django.contrib.auth.models import User +from django.contrib.auth.models import timezone +import uuid + +# Create your models here. +class Event(models.Model): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + name = models.CharField(max_length=200) + logo = models.CharField(max_length=200) + img = models.CharField(max_length=200) + description = models.TextField() + start_date = models.DateTimeField() + end_date = models.DateTimeField() + password = models.CharField(max_length=200, blank=True) + slug = models.SlugField(max_length=55) + def __str__(self): + return self.name + +class Scores(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + event = models.ForeignKey(Event, on_delete=models.CASCADE) + score = models.PositiveIntegerField(default=0, db_index=True) + last_submission_date = models.DateTimeField('Last Submission Date', default=timezone.now) + class Meta: + ordering = ['-score', 'last_submission_date', 'user__username'] \ No newline at end of file diff --git a/src/events/templates/events/ctf_info.html b/src/events/templates/events/ctf_info.html new file mode 100644 index 0000000..08c1900 --- /dev/null +++ b/src/events/templates/events/ctf_info.html @@ -0,0 +1,87 @@ +{% extends 'base.html' %} +{% block content %} +{% load i18n %} +
+
+
+ < Back to event +
+

Event - {{ event.name }}

+

{{ ctf.name }}

+ {% trans "Published date" %} : {{ ctf.pub_date }} +
+
+ {% if description %} + {{ description|safe }} + {% else %} + {% trans "No translation available. Please try another language (English or French)." %} + {% endif %} +
+ +
+
+

{% trans "Solved by" %}

+ {% if solved_list %} + + + + + + + + + + + {% for s in solved_list %} + + + + + + + {% endfor %} + +
{% trans "Username" %}{% trans "Website" %}{% trans "Score" %}{% trans "Date" %}
{{ s.user.username }}{{ s.user.userprofileinfo.portfolio_site }}{{ s.user.userprofileinfo.score }}{{ s.flag_date }}
+ {% else %} +

{% trans "Nobody have solved this CTF." %}

+ {% endif %} +
+
+ +
+{% endblock %} + diff --git a/src/events/templates/events/event_info.html b/src/events/templates/events/event_info.html new file mode 100644 index 0000000..5e6c20f --- /dev/null +++ b/src/events/templates/events/event_info.html @@ -0,0 +1,96 @@ +{% extends 'base.html' %} +{% block content %} +{% load i18n %} +{% load is_flagged %} +
+
+
+
+

{{ event.name }}

+ {% if ended == True %} + {% trans "This event is over." %} + {% else %} + {% trans "This event start at" %} : {{ event.start_date }} + {% endif %} +
+
+ {% if event.description %} + {{ event.description|safe }} + {% endif %} +
+ +
+
+

{% trans "ScoreBoard" %}

+ {% if solved_list %} + + + + + + + + + + + {% for s in solved_list %} + + + + + + + {% endfor %} + +
{% trans "Rank" %}{% trans "Username" %}{% trans "Website" %}{% trans "Score" %}
# {{ forloop.counter0|add:1 }} + {{ s.user.username }} + {{ s.user.userprofileinfo.site }}{{ s.score }}
+ {% else %} +

{% trans "Nobody have solved this CTF." %}

+ {% endif %} +
+
+ +
+{% endblock %} + diff --git a/src/events/templates/events/event_pwd.html b/src/events/templates/events/event_pwd.html new file mode 100644 index 0000000..7eb6853 --- /dev/null +++ b/src/events/templates/events/event_pwd.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} +{% block content %} +{% load i18n %} +
+
+
+
+

{{ event.name }}

+ {% trans "This event start at" %} : {{ event.start_date }} +
+ + +
+
+ +
+{% endblock %} + diff --git a/src/events/templates/events/events_list.html b/src/events/templates/events/events_list.html new file mode 100755 index 0000000..5d355b8 --- /dev/null +++ b/src/events/templates/events/events_list.html @@ -0,0 +1,47 @@ +{% extends 'base.html' %} +{% block content %} +{% load i18n %} +
+
+

Events

+
+ {% if events %} + {% for ev in events %} + {% if request.user.is_authenticated %} + + {% else %} + {% endif %} + {% if curdate > ev.end_date %} +
+ {% else %} +
+ {% endif %} +
+ ... +
+
{{ ev.name }}
+

+ Some quick example text to build on the card title and make up the bulk of the + card's content. +

+
+
    +
  • {{ ev.start_date }}
    -
    {{ ev.end_date }}
  • +
+
+ See more +
+
+
+ {% endfor %} + {% else %} +

{% trans "No events available." %}

+ {% endif %} +
+ +
+{% endblock %} diff --git a/src/events/templatetags/__init__.py b/src/events/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/events/templatetags/is_flagged.py b/src/events/templatetags/is_flagged.py new file mode 100644 index 0000000..259ac90 --- /dev/null +++ b/src/events/templatetags/is_flagged.py @@ -0,0 +1,10 @@ +from django import template +from ctfs.models import CTF_flags + +register = template.Library() + +@register.simple_tag +def isflagged(user, ctf): + if CTF_flags.objects.filter(user=user, ctf=ctf): + return "success-msg" + return "" diff --git a/src/events/tests.py b/src/events/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/src/events/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/src/events/urls.py b/src/events/urls.py new file mode 100644 index 0000000..1f8d495 --- /dev/null +++ b/src/events/urls.py @@ -0,0 +1,13 @@ +from django.urls import path +from . import views + +app_name = "events" + +urlpatterns = [ + path('', views.events, name='events'), + path('', views.event, name='event_info'), + path('/challenge/', views.chall_event_info, name='event_chall_info'), + path('pwd/', views.submit_pwd, name='submit_pwd'), + path('submitEventFlag//', views.submit_event_flag, name='submit_event_flag'), + path('subscribe/', views.subscribe_to_event, name='subscribe_event') +] diff --git a/src/events/views.py b/src/events/views.py new file mode 100644 index 0000000..3ffc009 --- /dev/null +++ b/src/events/views.py @@ -0,0 +1,143 @@ +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 +from .models import Event, Scores +from ctfs.models import CTF, CTF_flags +from django.utils.translation import get_language + +def get_description_by_lang(ctf): + lang = get_language() + ret = None + if lang == "fr": + ret = ctf.description + elif lang == "en": + ret = ctf.description_en + elif lang == "de": + ret = ctf.description_de + elif lang == "ru": + ret = ctf.description_ru + return ret + +# Create your views here. +def events(request): + list_events = Event.objects.filter().order_by('-end_date', 'start_date') + return render(request, 'events/events_list.html', {'events' : list_events, 'curdate': timezone.now()}) + +def chall_event_info(request, event_slug, chall_slug): + event_info = get_object_or_404(Event, slug=event_slug) + ctf_info = get_object_or_404(CTF, event__slug=event_info.slug, slug=chall_slug) + if request.user.is_authenticated and not request.user.is_staff: + userScore = Scores.objects.filter(event=event_info, user=request.user) + if not userScore: + return redirect('/') + solved_list = CTF_flags.objects.filter(ctf=ctf_info).order_by('flag_date') + description = get_description_by_lang(ctf_info) + return render(request, 'events/ctf_info.html', { 'ctf' : ctf_info, 'event':event_info, 'solved_list': solved_list, 'description': description}) + +def event(request, event_slug): + event_info = get_object_or_404(Event, slug=event_slug) + IsRegistered = False + if request.user.is_authenticated: + userScore = Scores.objects.filter(event=event_info, user=request.user) + if userScore: + IsRegistered = True + if event_info.password: + if request.user.is_authenticated: + if request.user.is_staff is False: + if not userScore: + return render(request, 'events/event_pwd.html', {'event' : event_info, 'logged': True}) + else: + return render(request, 'events/event_pwd.html', {'event' : event_info, 'logged': False}) + ended = False + if timezone.now() >= event_info.end_date: + ended = True + begun = False + if timezone.now() >= event_info.start_date: + begun = True + challenges = CTF.objects.filter(event=event_info).order_by('category', 'points') + solved_list = Scores.objects.filter(event=event_info).order_by('-score', 'last_submission_date', 'user__username') + return render(request, 'events/event_info.html', {'event' : event_info, 'IsRegistered': IsRegistered, 'ctfs': challenges, 'solved_list':solved_list, 'ended': ended, 'begun': begun}) + +@login_required +def submit_event_flag(request, event_slug, chall_slug): + ev = get_object_or_404(Event, slug=event_slug) + response = redirect('events:event_chall_info', event_slug=event_slug, chall_slug=chall_slug) + if timezone.now() >= ev.end_date: + response['Location'] += '?EventIsOver' + return response + + if request.method == 'POST': + ctf_info = CTF.objects.get(event=ev, slug=chall_slug) + if not ctf_info: + response['Location'] += '?ChallengeNotFound' + return response + flagged = False + if CTF_flags.objects.filter(user=request.user, ctf=ctf_info): + flagged = True + response['Location'] += '?AlreadyFlagged' + return response + try: + score = Scores.objects.get(user=request.user, event=ev) + except: + score = None + if score: + form = submit_flag(data=request.POST) + if flagged == False and form.is_valid(): + if ctf_info.flag == request.POST.get('flag'): + new = CTF_flags(user = request.user, ctf = ctf_info, flag_date = timezone.now()) + new.save() + score.last_submission_date = timezone.now() + score.score += ctf_info.points + score.save() + response['Location'] += '?Congrat' + return response + else: + response['Location'] += '?WrongFlag' + return response + else: + response['Location'] += '?ErrorInForm' + return response + return response + +@login_required +def submit_pwd(request, event_slug): + response = redirect('events:event_info', event_slug=event_slug) + if request.method == 'POST': + if request.user.is_authenticated: + ev = get_object_or_404(Event, slug=event_slug) + if ev == False: + response['Location'] += '?NoEventFound' + return response + + if request.POST.get('password') != ev.password: + response['Location'] += '?WrongPassword' + return response + + if Scores.objects.filter(user=request.user, event=ev).exists(): + response['Location'] += '?AlreadyRegistered' + return response + else: + new = Scores(user=request.user, event=ev, score=0) + new.save() + return redirect('events:event_info', event_slug=event_slug) + +@login_required +def subscribe_to_event(request, event_slug): + response = redirect('events:event_info', event_slug=event_slug) + if request.method == 'POST': + if request.user.is_authenticated: + ev = get_object_or_404(Event, slug=event_slug) + if ev == False: + response['Location'] += '?NoEventFound' + return response + if timezone.now() >= ev.end_date: + response['Location'] += '?SubscriptionIsOver' + return response + if Scores.objects.filter(user=request.user, event=ev).exists(): + response['Location'] += '?AlreadyRegistered' + return response + else: + new = Scores(user=request.user, event=ev, score=0) + new.save() + return redirect('events:event_info', event_slug=event_slug) diff --git a/src/home/views.py b/src/home/views.py index c5809a5..e9c4f08 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -32,7 +32,7 @@ def home(request): response = HttpResponseRedirect(url_translated) return response news = new.objects.order_by('-pub_date')[:5] - latest_ctfs = CTF.objects.order_by('-pub_date')[:5] + latest_ctfs = CTF.objects.filter(event=None).order_by('-pub_date')[:5] top10 = UserProfileInfo.objects.select_related().order_by('-score', 'last_submission_date', 'user__username')[:10] nb_flags = CTF_flags.objects.count() nb_users = UserProfileInfo.objects.count() diff --git a/src/project/settings.py b/src/project/settings.py index d1aec25..0a77e53 100644 --- a/src/project/settings.py +++ b/src/project/settings.py @@ -33,6 +33,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'home.apps.HomeConfig', 'ctfs.apps.CtfsConfig', + 'events.apps.EventsConfig', 'accounts.apps.AccountsConfig', 'scoreboard.apps.ScoreboardConfig', 'django.contrib.sites', diff --git a/src/project/urls.py b/src/project/urls.py index ffcef2d..dcfe0e2 100644 --- a/src/project/urls.py +++ b/src/project/urls.py @@ -32,5 +32,6 @@ urlpatterns += i18n_patterns( re_path('^accounts/login/', defaults.page_not_found, {'exception': Exception()}), path('accounts/', include('accounts.urls')), path('accounts/', include('django.contrib.auth.urls')), - path('scoreboard/', include('scoreboard.urls')) + path('scoreboard/', include('scoreboard.urls')), + path('events/', include('events.urls')) ) diff --git a/src/scoreboard/templates/scoreboard/scoreboard.html b/src/scoreboard/templates/scoreboard/scoreboard.html index 42772cc..e770812 100644 --- a/src/scoreboard/templates/scoreboard/scoreboard.html +++ b/src/scoreboard/templates/scoreboard/scoreboard.html @@ -5,50 +5,50 @@

Scoreboard

- +
- + - {% for s in scores %} - - - - - + {% for s in scores %} + + + + + - {% endfor %} + {% endfor %}
{% trans "Rank" %}{% trans "Rank" %} {% trans "Username" %} {% trans "Website" %} {% trans "Score" %}
# {{ forloop.counter0|add:scores.start_index }} {{ s.user.username }} - {% if s.user.userprofileinfo.portfolio_site %} - {{ s.user.userprofileinfo.portfolio_site }} - {% endif %} - {{ s.user.userprofileinfo.score }}
# {{ forloop.counter0|add:scores.start_index }} {{ s.user.username }} + {% if s.user.userprofileinfo.portfolio_site %} + {{ s.user.userprofileinfo.portfolio_site }} + {% endif %} + {{ s.user.userprofileinfo.score }}
- - +
+ +
{% endblock %} diff --git a/src/static/css/style.css b/src/static/css/style.css index f9577d4..682df7c 100644 --- a/src/static/css/style.css +++ b/src/static/css/style.css @@ -46,4 +46,4 @@ input[type=submit]:hover {background-color:#000} .progress {background-color: #2d2d2d;color:#000} .bg-success { background-color: #d9d9d9 !important; -} \ No newline at end of file +} diff --git a/src/statics/css/style.css b/src/statics/css/style.css index bc5bc77..307db14 100644 --- a/src/statics/css/style.css +++ b/src/statics/css/style.css @@ -1,5 +1,7 @@ body {background-color: #121212;color: #D9D9D9} .card-body {background-color: #1D1D1D;} +a{color:#cecece;} +a:hover{color:#a9a9a9;text-decoration: none;} .main-div{margin-top: 40px;} footer {text-align: center;} .news-card {margin-bottom: 20px; border: none;} @@ -41,9 +43,25 @@ input[type=submit]:hover {background-color:#000} .submitflag-form input[type=submit]:hover {background-color:#000} .edit-infos-grp input{width: 100%;} .message {display: block; padding:5px; text-align:center;margin-bottom: 10px;} -.success-msg {background-color: #42b35e4f;} +.success-msg {background-color: #42b35e4f!important;} .error-msg {background-color: #9542428c;} .progress {background-color: #2d2d2d;} .bg-success { background-color: #d9d9d9 !important;color: #000; -} \ No newline at end of file +} + +.event-card { + background-color: #1d1d1d; + min-height: 50vh; + margin-bottom: 13.37px; +} +.card-img-top{ + height:150px; +} +.chall-card{ + background-color: #131313; + min-height: 100px; + border-radius: 2px; + margin-bottom: 13.37px; +} +.is-over {opacity: 50%;} \ No newline at end of file diff --git a/src/templates/base.html b/src/templates/base.html index b9b5012..1d80305 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -2,89 +2,93 @@ {% load i18n %} - - - - - - - - 42CTF - - - - - - - - - - - - - - - - - - - - - -
- -