diff --git a/home/management/commands/delete_expired_accounts.py b/home/management/commands/delete_expired_accounts.py
new file mode 100644
index 00000000..859df59d
--- /dev/null
+++ b/home/management/commands/delete_expired_accounts.py
@@ -0,0 +1,31 @@
+from django.core.management.base import BaseCommand
+from django.utils import timezone
+from django.contrib.auth.models import User
+from home.models import UserDeletionRequest
+
+class Command(BaseCommand):
+ help = "Deletes user accounts that have been scheduled for deletion after 30 days"
+
+ def handle(self, *args, **kwargs):
+ now = timezone.now()
+ expired_requests = UserDeletionRequest.objects.filter(
+ scheduled_for__lte=now,
+ is_executed=False
+ )
+ if not expired_requests.exists():
+ self.stdout.write("No expired deletion requests to process.")
+ return
+
+ for deletion_request in expired_requests:
+ user = deletion_request.user
+ self.stdout.write(
+ f"Deleting user {user.username} (scheduled for {deletion_request.scheduled_for})"
+ )
+
+ user.delete() #user is deleted
+
+ deletion_request.is_executed = True
+ deletion_request.executed_at = now
+ deletion_request.save()
+
+ self.stdout.write(self.style.SUCCESS("Expired accounts deletion task complete."))
\ No newline at end of file
diff --git a/home/migrations/0001_initial.py b/home/migrations/0001_initial.py
index 1a3c7e61..73419598 100644
--- a/home/migrations/0001_initial.py
+++ b/home/migrations/0001_initial.py
@@ -609,4 +609,25 @@ class Migration(migrations.Migration):
'ordering': ['-published_at'],
},
),
+
+ migrations.CreateModel(
+ name='UserDeletionRequest',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('requested_at', models.DateTimeField(default=django.utils.timezone.now)),
+ ('scheduled_for', models.DateTimeField()),
+ ('is_executed', models.BooleanField(default=False)),
+ ('executed_at', models.DateTimeField(blank=True, null=True)),
+ ('user', models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='deletion_request',
+ to=settings.AUTH_USER_MODEL
+ )),
+ ],
+ ),
+
+
+
+
+
]
diff --git a/home/templates/accounts/confirm_delete.html b/home/templates/accounts/confirm_delete.html
index 45b45ad8..3bf3e0b3 100644
--- a/home/templates/accounts/confirm_delete.html
+++ b/home/templates/accounts/confirm_delete.html
@@ -1,8 +1,73 @@
-
Are you sure you want to delete your account?
-This action cannot be undone.
-
-
+{% load static %}
+
+{% block content %}
+
+
+
Confirm Account Action
+
+ {% if messages %}
+ {% for message in messages %}
+
+ {{ message }}
+
+
+ {% endfor %}
+ {% endif %}
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/home/views.py b/home/views.py
index 111e0dfb..7266f4b0 100644
--- a/home/views.py
+++ b/home/views.py
@@ -50,10 +50,11 @@
from .models import Article, Student, Project, Contact, Smishingdetection_join_us, Projects_join_us, Webpage, Profile, User, Course, Skill, Experience, Job, JobAlert, UserBlogPage, VaultDocument #Feedback
-
+from django.contrib.auth.hashers import check_password
from django.contrib.auth import get_user_model
from .models import User
from django.utils import timezone
+from datetime import timedelta
from django.core.mail import send_mail
from django.core.exceptions import ValidationError
from django.utils.http import urlsafe_base64_encode
@@ -173,6 +174,8 @@ def wrapped_view(request, *args, **kwargs):
from .forms import PenTestingRequestForm, SecureCodeReviewRequestForm
from .models import AppAttackReport
+from .models import UserDeletionRequest
+
from home.models import TeamMember
@@ -3631,11 +3634,60 @@ def secure_code_review_form_view(request):
def delete_account(request):
if request.method == 'POST':
user = request.user
- user.delete()
- logout(request)
- messages.success(request, "Your account has been deleted.")
- return redirect('login')
- return HttpResponseNotAllowed(['POST'])
+ choice = request.POST.get("choice")
+ password = request.POST.get("password")
+
+ if not password:
+ messages.error(request, "Password Required")
+ return render(request, "accounts/confirm_delete.html")
+
+ if not check_password(password, user.password):
+ messages.error(request, "Incorrect password. Please try again.")
+ return redirect('delete-account')
+
+ if choice == "deactivate":
+ logout(request)
+ send_mail(
+ "Account Deactivated",
+ "Your account has been temporarily deactivated. Log in again to reactivate.",
+ "admin@example.com",
+ [user.email],
+ )
+ messages.success(request, "Your account has been deactivated.")
+ return redirect('login')
+
+ elif choice == "delete_now":
+ email = user.email
+ user.delete()
+ send_mail(
+ "Account Deleted",
+ "Your account has been permanently deleted.",
+ "admin@example.com",
+ [email],
+ )
+ messages.success(request, "Your account has been permanently deleted.")
+ return redirect('login')
+
+ elif choice == "delete_30days":
+ UserDeletionRequest.objects.update_or_create(
+ user=user,
+ defaults={"scheduled_for": timezone.now() + timedelta(days=30)}
+ )
+ logout(request)
+ send_mail(
+ "Account Scheduled for Deletion",
+ "Your account is deactivated and will be permanently deleted in 30 days unless reactivated.",
+ "admin@example.com",
+ [user.email],
+ )
+ messages.success(request, "Your account is scheduled for deletion in 30 days.")
+ return redirect('login')
+
+ else:
+ messages.error(request, "Invalid option.")
+ return redirect('delete-account')
+
+ return render(request, "accounts/confirm_delete.html")
def tools_home(request):
return render(request, 'pages/pt_gui/tools/index.html')