Skip to content

Commit

Permalink
implemented forgot password feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
harshuln123 committed Jan 1, 2025
1 parent 7d45b9c commit 66508e7
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 0 deletions.
32 changes: 32 additions & 0 deletions FusionIIIT/Fusion/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import path

from applications.globals.views import RateLimitedPasswordResetView


urlpatterns = [
Expand Down Expand Up @@ -62,4 +65,33 @@
url(r'^recruitment/', include('applications.recruitment.urls')),
url(r'^examination/', include('applications.examination.urls')),
url(r'^otheracademic/', include('applications.otheracademic.urls')),

path(
'password-reset/',
RateLimitedPasswordResetView.as_view(
template_name='registration/password_reset_form.html',
),
name='reset_password',
),
path(
'password-reset/done/',
auth_views.PasswordResetDoneView.as_view(
template_name='registration/password_reset_done.html'
),
name='password_reset_done',
),
path(
'reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(
template_name='registration/password_reset_confirm.html',
),
name='password_reset_confirm',
),
path(
'reset/done/',
auth_views.PasswordResetCompleteView.as_view(
template_name='registration/password_reset_complete.html'
),
name='password_reset_complete',
),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.1.5 on 2025-01-01 15:10

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('globals', '0002_moduleaccess'),
]

operations = [
migrations.CreateModel(
name='PasswordResetTracker',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(max_length=254, unique=True)),
('last_reset', models.DateTimeField(blank=True, null=True)),
],
),
]
8 changes: 8 additions & 0 deletions FusionIIIT/applications/globals/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,11 @@ class ModuleAccess(models.Model):

def __str__(self):
return self.designation


class PasswordResetTracker(models.Model):
email = models.EmailField(unique=True)
last_reset = models.DateTimeField(null=True, blank=True)

def __str__(self):
return self.email
39 changes: 39 additions & 0 deletions FusionIIIT/applications/globals/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,45 @@
from .models import *
from applications.hostel_management.models import (HallCaretaker,HallWarden)


from django.contrib.auth.views import PasswordResetView
from django.shortcuts import render
from django.utils.timezone import now
from datetime import timedelta
from .models import PasswordResetTracker

class RateLimitedPasswordResetView(PasswordResetView):
template_name = 'registration/password_reset_form.html' # Customize as needed

def post(self, request, *args, **kwargs):
email = request.POST.get('email')
if not email:
return self.form_invalid(self.get_form()) # Default behavior for invalid forms

# Check if the email exists in the tracker table
tracker, created = PasswordResetTracker.objects.get_or_create(email=email)

# Enforce rate limiting: Check if the reset was within the last 24 hours
if tracker.last_reset and now() - tracker.last_reset < timedelta(days=1):
# Pass error message to the template
return render(
request,
self.template_name,
{
'form': self.get_form(), # Include the form for re-rendering
'error_message': "Password can only be reset once every 24 hours.",
},
)

# Update the tracker with the current timestamp
tracker.last_reset = now()
tracker.save()

# Proceed with the standard password reset process
return super().post(request, *args, **kwargs)



def index(request):
context = {}
if(str(request.user)!="AnonymousUser"):
Expand Down
5 changes: 5 additions & 0 deletions FusionIIIT/templates/account/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
</div> -->
</form>

<div class="ui bottom attached warning message">
<i class="icon help"></i>
<a href="/password-reset">Forgot Password</a>.
</div>

<div class="box-header with-border">
{% get_providers as socialaccount_providers %}
</div>
Expand Down
13 changes: 13 additions & 0 deletions FusionIIIT/templates/registration/password_reset_complete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Password Reset Successful</title>
</head>
<body>
<h2>Password Reset Successful</h2>
<p>Your password has been reset successfully. You can now log in with your new password.</p>
<p><a href="/accounts/login/">Log In</a></p>
</body>
</html>
63 changes: 63 additions & 0 deletions FusionIIIT/templates/registration/password_reset_confirm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% extends "account/base.html" %}
{% block content %}
{% load i18n %}
{% load account socialaccount %}
{% load static semanticui %}

<!-- <div class="content">
<img class="ui rounded centered small image"
src="{% static 'globals/img/user.png' %}"
style="margin-top: -27.5%; margin-left: 27.5%;"
alt="User Image">
<div class="ui huge centered header">
Login
</div>
</div> -->

<div class="content">
<div>
<h2 style="margin-bottom: 10px; text-align: center;">Set New Password</h2>
</div>
<form method="POST" class="ui form" style="margin-top: 2.5%;margin-bottom: 2.5%;">
{% csrf_token %}
{{ form.as_p }}
<button class = "fluid ui primary button" type="submit" style="margin-top: 20px;margin-bottom:10px">Reset Password</button>
</form>
</div>


{% if form.errors %}
<div id="error-popup" class="ui modal">
<div class="header">Reset Failed</div>
<div class="content">
<ul>
{% for field in form %}
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
<div class="actions">
<div class="ui red ok button">OK</div>
</div>
</div>
{% endif %}

<script>
document.addEventListener('DOMContentLoaded', function () {
if (document.getElementById('error-popup')) {
$('#error-popup').modal({
onApprove: function() {
$('#error-popup').modal('hide');
}
}).modal('show');
}
});
</script>


{% endblock %}
13 changes: 13 additions & 0 deletions FusionIIIT/templates/registration/password_reset_done.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Password Reset Sent</title>
</head>
<body>
<h2>Check Your Email</h2>
<p>If your email address is associated with an account, you will receive a password reset email shortly.</p>
<p><a href="/">Back to Home</a></p>
</body>
</html>
55 changes: 55 additions & 0 deletions FusionIIIT/templates/registration/password_reset_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{% extends "account/base.html" %}
{% block content %}
{% load i18n %}
{% load account socialaccount %}
{% load static semanticui %}

<!-- <div class="content">
<img class="ui rounded centered small image"
src="{% static 'globals/img/user.png' %}"
style="margin-top: -27.5%; margin-left: 27.5%;"
alt="User Image">
<div class="ui huge centered header">
Login
</div>
</div> -->

<div class="content">
<div>
<h2 style="margin-bottom: 10px; text-align: center;">Forgot Your Password?</h2>
<p style="text-align: center;">Enter your email address below, and we'll send you a link to reset your password.</p>
</div>
<form method="POST" class="ui form" style="margin-top: 2.5%;margin-bottom: 2.5%;">
{% csrf_token %}
{{ form.as_p }}
<button class = "fluid ui primary button" type="submit" style="margin-top: 20px;margin-bottom:10px">Send Reset Link</button>
</form>
</div>

{% if error_message %}
<div id="error-popup" class="ui modal">
<div class="header">Reset Failed</div>
<div class="content">
<ul>
<li>{{ error_message }}</li>
</ul>
</div>
<div class="actions">
<div class="ui red ok button">OK</div>
</div>
</div>
{% endif %}

<script>
document.addEventListener('DOMContentLoaded', function () {
if (document.getElementById('error-popup')) {
$('#error-popup').modal({
onApprove: function() {
$('#error-popup').modal('hide');
}
}).modal('show');
}
});
</script>

{% endblock %}

0 comments on commit 66508e7

Please sign in to comment.