From 48442f44a3b4178f2a8a9470d1fab7567c1350e6 Mon Sep 17 00:00:00 2001 From: Lucky negi Date: Sun, 15 Jun 2025 14:34:45 +0530 Subject: [PATCH 1/4] only frontedn dashboard --- blt/urls.py | 2 + website/templates/Simulation.html | 93 +++++++++++++++++++++++++++++++ website/views/Simulation.py | 50 +++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 website/templates/Simulation.html create mode 100644 website/views/Simulation.py diff --git a/blt/urls.py b/blt/urls.py index 6ad05810a3..de8455c584 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -276,6 +276,7 @@ ) from website.views.queue import queue_list, update_txid from website.views.repo import RepoListView, add_repo, refresh_repo_data +from website.views.Simulation import dashboard from website.views.slack_handlers import slack_commands, slack_events from website.views.social import queue_social_view from website.views.teams import ( @@ -359,6 +360,7 @@ handler500 = "website.views.core.handler500" urlpatterns = [ + path("simulation/", dashboard, name="dashboard"), path("banned_apps/", BannedAppsView.as_view(), name="banned_apps"), path("api/banned_apps/search/", search_banned_apps, name="search_banned_apps"), path("500/", TemplateView.as_view(template_name="500.html"), name="500"), diff --git a/website/templates/Simulation.html b/website/templates/Simulation.html new file mode 100644 index 0000000000..763288ad0f --- /dev/null +++ b/website/templates/Simulation.html @@ -0,0 +1,93 @@ + +{% extends 'base.html' %} +{% block content %} +
+ +
+
+

Security Labs

+
+
+ +
+
+ +
+ {% for lab in labs %} +
+
+ +
+ +
+ {% if lab.icon == 'database' %} + + + + {% elif lab.icon == 'code' %} + + + + {% elif lab.icon == 'shield-check' %} + + + + {% elif lab.icon == 'terminal' %} + + + + {% endif %} +

{{ lab.title }}

+
+ + {{ lab.total_tasks }} Tasks +
+ +

{{ lab.description }}

+ +
+
+
+
+
Progress: {{ lab.progress }}%
+
+ + +
+
+ {% endfor %} +
+
+
+
+{% endblock %} diff --git a/website/views/Simulation.py b/website/views/Simulation.py new file mode 100644 index 0000000000..89eb5aba74 --- /dev/null +++ b/website/views/Simulation.py @@ -0,0 +1,50 @@ +# website/views/Simulation.py + +from django.contrib.auth.decorators import login_required +from django.shortcuts import render + +# from website.models import Lab, UserProgress + + +@login_required +def dashboard(request): + labs_data = [ + { + "id": "sql-injection", + "title": "SQL Injection", + "description": "Learn about SQL injection vulnerabilities and how to exploit them", + "icon": "database", # For heroicons + "total_tasks": 10, + "color": "#e74c3c", + "progress": 0, # We'll calculate this + }, + { + "id": "xss", + "title": "Cross-Site Scripting (XSS)", + "description": "Master the art of identifying and exploiting XSS vulnerabilities", + "icon": "code", + "total_tasks": 8, + "color": "#e74c3c", + "progress": 0, + }, + { + "id": "csrf", + "title": "Cross-Site Request Forgery", + "description": "Understand CSRF attacks and prevention techniques", + "icon": "shield-check", + "total_tasks": 6, + "color": "#e74c3c", + "progress": 0, + }, + { + "id": "command-injection", + "title": "Command Injection", + "description": "Learn about command injection vulnerabilities and exploitation", + "icon": "terminal", + "total_tasks": 7, + "color": "#e74c3c", + "progress": 0, + }, + ] + + return render(request, "Simulation.html", {"labs": labs_data}) From 9fed9cc935d2947bc896bfeb23d24cb452efcd39 Mon Sep 17 00:00:00 2001 From: Lucky negi Date: Mon, 30 Jun 2025 19:33:52 +0530 Subject: [PATCH 2/4] Add Labs model and initial data creation command - Introduced a new Labs model with fields for name, description, estimated time, total tasks, and active status. - Added a management command to create initial lab data for SQL Injection, XSS, CSRF, and Command Injection. - Updated the dashboard view to fetch and display active labs with their respective details. New labs created, Knowledge in every task, Learning never ends. --- .../commands/create_initial_labs.py | 56 +++++++++++++++++ website/migrations/0242_labs.py | 32 ++++++++++ website/models.py | 26 ++++++++ website/templates/Simulation.html | 7 ++- website/views/Simulation.py | 62 +++++++------------ 5 files changed, 143 insertions(+), 40 deletions(-) create mode 100644 website/management/commands/create_initial_labs.py create mode 100644 website/migrations/0242_labs.py diff --git a/website/management/commands/create_initial_labs.py b/website/management/commands/create_initial_labs.py new file mode 100644 index 0000000000..1604f5bf33 --- /dev/null +++ b/website/management/commands/create_initial_labs.py @@ -0,0 +1,56 @@ +from django.core.management.base import BaseCommand +from website.models import Labs + + +class Command(BaseCommand): + help = 'Creates initial security lab data' + + def handle(self, *args, **kwargs): + # Define the initial labs + labs_data = [ + { + "name": "SQL Injection", + "description": "Learn about SQL injection vulnerabilities and how to exploit them. This lab covers basic to advanced SQL injection techniques, including union-based, error-based, and blind SQL injection.", + "estimated_time": 60, # 60 minutes + "order": 1, + }, + { + "name": "Cross-Site Scripting (XSS)", + "description": "Master the art of identifying and exploiting XSS vulnerabilities. Learn about different types of XSS attacks including reflected, stored, and DOM-based XSS.", + "estimated_time": 45, # 45 minutes + "order": 2, + }, + { + "name": "Cross-Site Request Forgery", + "description": "Understand CSRF attacks and prevention techniques. Learn how to identify CSRF vulnerabilities and implement proper protection mechanisms.", + "estimated_time": 30, # 30 minutes + "order": 3, + }, + { + "name": "Command Injection", + "description": "Learn about command injection vulnerabilities and exploitation. This lab covers how to identify and exploit command injection flaws in web applications.", + "estimated_time": 40, # 40 minutes + "order": 4, + }, + ] + + # Create the labs + for lab_data in labs_data: + lab, created = Labs.objects.get_or_create( + name=lab_data["name"], + defaults={ + "description": lab_data["description"], + "estimated_time": lab_data["estimated_time"], + "order": lab_data["order"], + "is_active": True, + } + ) + + if created: + self.stdout.write( + self.style.SUCCESS(f'Successfully created lab "{lab.name}"') + ) + else: + self.stdout.write( + self.style.WARNING(f'Lab "{lab.name}" already exists') + ) \ No newline at end of file diff --git a/website/migrations/0242_labs.py b/website/migrations/0242_labs.py new file mode 100644 index 0000000000..7811331630 --- /dev/null +++ b/website/migrations/0242_labs.py @@ -0,0 +1,32 @@ +# Generated by Django 5.1.8 on 2025-06-30 14:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("website", "0241_domain_has_security_txt_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="Labs", + fields=[ + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=255)), + ("description", models.TextField()), + ("estimated_time", models.PositiveIntegerField(help_text="Estimated time in minutes")), + ("total_tasks", models.PositiveIntegerField(default=0)), + ("is_active", models.BooleanField(default=True)), + ("order", models.PositiveIntegerField(default=0)), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ], + options={ + "verbose_name": "Lab", + "verbose_name_plural": "Labs", + "ordering": ["order"], + }, + ), + ] diff --git a/website/models.py b/website/models.py index bd4226cbe4..f58901826a 100644 --- a/website/models.py +++ b/website/models.py @@ -2453,6 +2453,32 @@ class Meta: def __str__(self): return f"{self.app_name} (Banned in {self.country_name})" +class Labs(models.Model): + name = models.CharField(max_length=255) + description = models.TextField() + estimated_time = models.PositiveIntegerField(help_text="Estimated time in minutes") + total_tasks = models.PositiveIntegerField(default=0) # Keep this field but default to 0 + is_active = models.BooleanField(default=True) + order = models.PositiveIntegerField(default=0) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def update_total_tasks(self): + """ + Updates the total_tasks count based on related tasks. + This will be called when tasks are added/removed. + """ + if hasattr(self, 'tasks'): + self.total_tasks = self.tasks.count() + self.save() + + def __str__(self): + return self.name + + class Meta: + verbose_name = "Lab" + verbose_name_plural = "Labs" + ordering = ["order"] class Notification(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notifications") diff --git a/website/templates/Simulation.html b/website/templates/Simulation.html index 763288ad0f..e3de1babc6 100644 --- a/website/templates/Simulation.html +++ b/website/templates/Simulation.html @@ -55,8 +55,11 @@

Security Labs

{% endif %}

{{ lab.title }}

- - {{ lab.total_tasks }} Tasks + +
+ {{ lab.total_tasks }} Tasks + {{ lab.estimated_time }} min +

{{ lab.description }}

diff --git a/website/views/Simulation.py b/website/views/Simulation.py index 89eb5aba74..f1f9f80c6f 100644 --- a/website/views/Simulation.py +++ b/website/views/Simulation.py @@ -3,48 +3,34 @@ from django.contrib.auth.decorators import login_required from django.shortcuts import render -# from website.models import Lab, UserProgress +from website.models import Labs @login_required def dashboard(request): - labs_data = [ - { - "id": "sql-injection", - "title": "SQL Injection", - "description": "Learn about SQL injection vulnerabilities and how to exploit them", - "icon": "database", # For heroicons - "total_tasks": 10, + # Get all active labs ordered by their order field + labs = Labs.objects.filter(is_active=True).order_by('order') + + labs_data = [] + for lab in labs: + # Map lab icons based on lab name or add a default + icon = "database" # Default icon + if "xss" in lab.name.lower(): + icon = "code" + elif "csrf" in lab.name.lower(): + icon = "shield-check" + elif "command" in lab.name.lower(): + icon = "terminal" + + labs_data.append({ + "id": lab.id, + "title": lab.name, + "description": lab.description, + "icon": icon, + "total_tasks": lab.total_tasks, "color": "#e74c3c", - "progress": 0, # We'll calculate this - }, - { - "id": "xss", - "title": "Cross-Site Scripting (XSS)", - "description": "Master the art of identifying and exploiting XSS vulnerabilities", - "icon": "code", - "total_tasks": 8, - "color": "#e74c3c", - "progress": 0, - }, - { - "id": "csrf", - "title": "Cross-Site Request Forgery", - "description": "Understand CSRF attacks and prevention techniques", - "icon": "shield-check", - "total_tasks": 6, - "color": "#e74c3c", - "progress": 0, - }, - { - "id": "command-injection", - "title": "Command Injection", - "description": "Learn about command injection vulnerabilities and exploitation", - "icon": "terminal", - "total_tasks": 7, - "color": "#e74c3c", - "progress": 0, - }, - ] + "progress": 0, # We'll implement progress tracking in the next PR + "estimated_time": lab.estimated_time + }) return render(request, "Simulation.html", {"labs": labs_data}) From fc038706859e8ebb75927abbc0db4414c75170aa Mon Sep 17 00:00:00 2001 From: Lucky negi Date: Mon, 30 Jun 2025 23:39:47 +0530 Subject: [PATCH 3/4] pre_commit_done --- .../commands/create_initial_labs.py | 15 ++++------ website/migrations/0242_labs.py | 1 - website/models.py | 4 ++- website/views/Simulation.py | 28 ++++++++++--------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/website/management/commands/create_initial_labs.py b/website/management/commands/create_initial_labs.py index 1604f5bf33..9d48c26d77 100644 --- a/website/management/commands/create_initial_labs.py +++ b/website/management/commands/create_initial_labs.py @@ -1,9 +1,10 @@ from django.core.management.base import BaseCommand + from website.models import Labs class Command(BaseCommand): - help = 'Creates initial security lab data' + help = "Creates initial security lab data" def handle(self, *args, **kwargs): # Define the initial labs @@ -43,14 +44,10 @@ def handle(self, *args, **kwargs): "estimated_time": lab_data["estimated_time"], "order": lab_data["order"], "is_active": True, - } + }, ) - + if created: - self.stdout.write( - self.style.SUCCESS(f'Successfully created lab "{lab.name}"') - ) + self.stdout.write(self.style.SUCCESS(f'Successfully created lab "{lab.name}"')) else: - self.stdout.write( - self.style.WARNING(f'Lab "{lab.name}" already exists') - ) \ No newline at end of file + self.stdout.write(self.style.WARNING(f'Lab "{lab.name}" already exists')) diff --git a/website/migrations/0242_labs.py b/website/migrations/0242_labs.py index 7811331630..72264704ed 100644 --- a/website/migrations/0242_labs.py +++ b/website/migrations/0242_labs.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("website", "0241_domain_has_security_txt_and_more"), ] diff --git a/website/models.py b/website/models.py index f58901826a..0d548898b6 100644 --- a/website/models.py +++ b/website/models.py @@ -2453,6 +2453,7 @@ class Meta: def __str__(self): return f"{self.app_name} (Banned in {self.country_name})" + class Labs(models.Model): name = models.CharField(max_length=255) description = models.TextField() @@ -2468,7 +2469,7 @@ def update_total_tasks(self): Updates the total_tasks count based on related tasks. This will be called when tasks are added/removed. """ - if hasattr(self, 'tasks'): + if hasattr(self, "tasks"): self.total_tasks = self.tasks.count() self.save() @@ -2480,6 +2481,7 @@ class Meta: verbose_name_plural = "Labs" ordering = ["order"] + class Notification(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notifications") message = models.TextField() diff --git a/website/views/Simulation.py b/website/views/Simulation.py index f1f9f80c6f..0589725ff8 100644 --- a/website/views/Simulation.py +++ b/website/views/Simulation.py @@ -9,8 +9,8 @@ @login_required def dashboard(request): # Get all active labs ordered by their order field - labs = Labs.objects.filter(is_active=True).order_by('order') - + labs = Labs.objects.filter(is_active=True).order_by("order") + labs_data = [] for lab in labs: # Map lab icons based on lab name or add a default @@ -21,16 +21,18 @@ def dashboard(request): icon = "shield-check" elif "command" in lab.name.lower(): icon = "terminal" - - labs_data.append({ - "id": lab.id, - "title": lab.name, - "description": lab.description, - "icon": icon, - "total_tasks": lab.total_tasks, - "color": "#e74c3c", - "progress": 0, # We'll implement progress tracking in the next PR - "estimated_time": lab.estimated_time - }) + + labs_data.append( + { + "id": lab.id, + "title": lab.name, + "description": lab.description, + "icon": icon, + "total_tasks": lab.total_tasks, + "color": "#e74c3c", + "progress": 0, # We'll implement progress tracking in the next PR + "estimated_time": lab.estimated_time, + } + ) return render(request, "Simulation.html", {"labs": labs_data}) From 69efe93ecfa38590107eb0c44c22c7ae94376bd4 Mon Sep 17 00:00:00 2001 From: Lucky negi Date: Fri, 4 Jul 2025 21:20:11 +0530 Subject: [PATCH 4/4] for_passing_test --- website/views/Simulation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/views/Simulation.py b/website/views/Simulation.py index 0589725ff8..5dc329b792 100644 --- a/website/views/Simulation.py +++ b/website/views/Simulation.py @@ -30,7 +30,7 @@ def dashboard(request): "icon": icon, "total_tasks": lab.total_tasks, "color": "#e74c3c", - "progress": 0, # We'll implement progress tracking in the next PR + "progress": 0, # We'll implement progress tracking in the next PR_forward "estimated_time": lab.estimated_time, } )