Skip to content

Commit d9917ba

Browse files
author
mominur-helios
committed
add change password in profile page
1 parent b2c0598 commit d9917ba

File tree

5 files changed

+126
-37
lines changed

5 files changed

+126
-37
lines changed

apps/users/urls.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
path('signin/', views.SignInView.as_view(), name="signin"),
99
path('signup/', views.SignUpView.as_view(), name="signup"),
1010
path('signout/', views.signout_view, name="signout"),
11-
path('password-change/', views.UserPasswordChangeView.as_view(), name='password_change'),
12-
path('password-change-done/', auth_views.PasswordChangeDoneView.as_view(
13-
template_name='authentication/password-change-done.html'
14-
), name="password_change_done"),
11+
# path('password-change/', views.UserPasswordChangeView.as_view(), name='password_change'),
12+
# path('password-change-done/', auth_views.PasswordChangeDoneView.as_view(
13+
# template_name='authentication/password-change-done.html'
14+
# ), name="password_change_done"),
1515
path('password-reset/', views.UserPasswordResetView.as_view(), name="password_reset"),
1616
path('password-reset-confirm/<uidb64>/<token>/',
1717
views.UserPasswrodResetConfirmView.as_view(), name="password_reset_confirm"
@@ -25,4 +25,5 @@
2525

2626
path('profile/', views.profile, name='profile'),
2727
path('upload-avatar/', views.upload_avatar, name='upload_avatar'),
28+
path('change-password', views.change_password, name='change_password'),
2829
]

apps/users/views.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from django.contrib.auth import logout
99
from django.urls import reverse
1010
from django.contrib.auth.decorators import login_required
11+
from django.contrib.auth.hashers import check_password
12+
from django.contrib import messages
1113

1214
# Create your views here.
1315

@@ -57,6 +59,7 @@ def profile(request):
5759

5860
if form.is_valid():
5961
form.save()
62+
messages.success(request, 'Profile updated successfully')
6063
else:
6164
form = ProfileForm(instance=profile)
6265

@@ -71,4 +74,16 @@ def upload_avatar(request):
7174
if request.method == 'POST':
7275
profile.avatar = request.FILES.get('avatar')
7376
profile.save()
77+
messages.success(request, 'Avatar uploaded successfully')
78+
return redirect(request.META.get('HTTP_REFERER'))
79+
80+
81+
def change_password(request):
82+
user = request.user
83+
if request.method == 'POST':
84+
if check_password(request.POST.get('current_password'), user.password):
85+
user.set_password(request.POST.get('new_password'))
86+
messages.success(request, 'Password changed successfully')
87+
else:
88+
messages.error(request, "Password doesn't match!")
7489
return redirect(request.META.get('HTTP_REFERER'))

core/settings.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from pathlib import Path
1515
from dotenv import load_dotenv
1616
from distutils.util import strtobool
17+
from django.contrib import messages
1718

1819
load_dotenv() # take environment variables from .env.
1920

@@ -195,4 +196,12 @@
195196
}
196197

197198
# risky
198-
SESSION_COOKIE_HTTPONLY=False
199+
SESSION_COOKIE_HTTPONLY=False
200+
201+
202+
MESSAGE_TAGS = {
203+
messages.INFO: 'text-blue-800 border border-blue-300 bg-blue-50 dark:text-blue-400 dark:border-blue-800',
204+
messages.SUCCESS: 'text-green-800 border border-green-300 bg-green-50 dark:text-green-400 dark:border-green-800',
205+
messages.WARNING: 'text-yellow-800 border border-yellow-300 bg-yellow-50 dark:text-yellow-300 dark:border-yellow-800',
206+
messages.ERROR: 'text-red-800 border border-red-300 bg-red-50 dark:text-red-400 dark:border-red-800',
207+
}

templates/layouts/base.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
<body class="bg-gray-50 dark:bg-gray-800">
1414

15+
{% block messages %}{% endblock messages %}
16+
1517
{% block navigation %}
1618
{% include "includes/navigation.html" %}
1719
{% endblock navigation %}

templates/pages/dashboard/profile.html

Lines changed: 94 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
{% extends "layouts/base.html" %}
22
{% load static %}
33

4+
{% block messages %}
5+
6+
{% if messages %}
7+
{% for message in messages %}
8+
<div class="flex items-center p-4 text-sm rounded-lg dark:bg-gray-800 {{message.tags}}" role="alert">
9+
<svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
10+
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"/>
11+
</svg>
12+
<span class="sr-only">Info</span>
13+
<div>{{ message }}</div>
14+
</div>
15+
{% endfor %}
16+
{% endif %}
17+
18+
19+
{% endblock messages %}
420

521
{% block content %}
622

@@ -117,41 +133,36 @@ <h3 class="mb-4 text-xl font-semibold dark:text-white">General information</h3>
117133
</div>
118134
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
119135
<h3 class="mb-4 text-xl font-semibold dark:text-white">Password information</h3>
120-
<form action="#">
136+
<form method="post" action="{% url "change_password" %}">
137+
{% csrf_token %}
138+
121139
<div class="grid grid-cols-6 gap-6">
122140
<div class="col-span-6 sm:col-span-3">
123-
<label for="current-password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Current password</label>
124-
<input type="text" name="current-password" id="current-password" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="••••••••" required>
141+
<label for="current_password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Current password</label>
142+
<div class="relative w-full">
143+
<input type="password" id="current_password" name="current_password" class="block p-2.5 w-full z-20 text-sm text-gray-900 bg-gray-50 rounded-lg border-l-gray-100 border-l-2 border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:border-blue-500" placeholder="Current password" required>
144+
<button type="button" id="show_current_password" class="absolute top-0 right-0 p-2.5 h-full text-sm font-thin text-white rounded-r-lg">
145+
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 14">
146+
<g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
147+
<path d="M10 10a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
148+
<path d="M10 13c4.97 0 9-2.686 9-6s-4.03-6-9-6-9 2.686-9 6 4.03 6 9 6Z"/>
149+
</g>
150+
</svg>
151+
</button>
152+
</div>
125153
</div>
126154
<div class="col-span-6 sm:col-span-3">
127-
<label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">New password</label>
128-
<input data-popover-target="popover-password" data-popover-placement="bottom" type="password" id="password" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="••••••••" required>
129-
<div data-popover id="popover-password" role="tooltip" class="absolute z-10 invisible inline-block text-sm font-light text-gray-500 transition-opacity duration-300 bg-white border border-gray-200 rounded-lg shadow-sm opacity-0 w-72 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400">
130-
<div class="p-3 space-y-2">
131-
<h3 class="font-semibold text-gray-900 dark:text-white">Must have at least 6 characters</h3>
132-
<div class="grid grid-cols-4 gap-2">
133-
<div class="h-1 bg-orange-300 dark:bg-orange-400"></div>
134-
<div class="h-1 bg-orange-300 dark:bg-orange-400"></div>
135-
<div class="h-1 bg-gray-200 dark:bg-gray-600"></div>
136-
<div class="h-1 bg-gray-200 dark:bg-gray-600"></div>
137-
</div>
138-
<p>It’s better to have:</p>
139-
<ul>
140-
<li class="flex items-center mb-1">
141-
<svg class="w-4 h-4 mr-2 text-green-400 dark:text-green-500" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path></svg>
142-
Upper & lower case letters
143-
</li>
144-
<li class="flex items-center mb-1">
145-
<svg class="w-4 h-4 mr-2 text-gray-300 dark:text-gray-400" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
146-
A symbol (#$&)
147-
</li>
148-
<li class="flex items-center">
149-
<svg class="w-4 h-4 mr-2 text-gray-300 dark:text-gray-400" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
150-
A longer password (min. 12 chars.)
151-
</li>
152-
</ul>
153-
</div>
154-
<div data-popper-arrow></div>
155+
<label for="new_password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Current password</label>
156+
<div class="relative w-full">
157+
<input type="password" id="new_password" name="new_password" class="block p-2.5 w-full z-20 text-sm text-gray-900 bg-gray-50 rounded-lg border-l-gray-100 border-l-2 border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:border-blue-500" placeholder="New password" required>
158+
<button type="button" id="show_new_password" class="absolute top-0 right-0 p-2.5 h-full text-sm font-thin text-white rounded-r-lg">
159+
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 14">
160+
<g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
161+
<path d="M10 10a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
162+
<path d="M10 13c4.97 0 9-2.686 9-6s-4.03-6-9-6-9 2.686-9 6 4.03 6 9 6Z"/>
163+
</g>
164+
</svg>
165+
</button>
155166
</div>
156167
</div>
157168
<div class="col-span-6 sm:col-full">
@@ -164,4 +175,55 @@ <h3 class="font-semibold text-gray-900 dark:text-white">Must have at least 6 cha
164175

165176
</div>
166177

167-
{% endblock content %}
178+
{% endblock content %}
179+
180+
181+
{% block extra_js %}
182+
183+
<script>
184+
document.addEventListener('DOMContentLoaded', function () {
185+
const currentPasswordInput = document.getElementById('current_password');
186+
const newPasswordInput = document.getElementById('new_password');
187+
const showCurrentPasswordButton = document.getElementById('show_current_password');
188+
const showNewPasswordButton = document.getElementById('show_new_password');
189+
190+
showCurrentPasswordButton.addEventListener('click', function () {
191+
togglePasswordVisibility(currentPasswordInput, showCurrentPasswordButton);
192+
});
193+
194+
showNewPasswordButton.addEventListener('click', function () {
195+
togglePasswordVisibility(newPasswordInput, showNewPasswordButton);
196+
});
197+
198+
function togglePasswordVisibility(input, button) {
199+
const type = input.getAttribute('type') === 'password' ? 'text' : 'password';
200+
input.setAttribute('type', type);
201+
202+
toggleEyeIcon(button, type);
203+
}
204+
205+
function toggleEyeIcon(button, type) {
206+
const eyeIcon = button.querySelector('svg');
207+
208+
if (type === 'password') {
209+
eyeIcon.innerHTML = `
210+
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 14">
211+
<g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
212+
<path d="M10 10a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
213+
<path d="M10 13c4.97 0 9-2.686 9-6s-4.03-6-9-6-9 2.686-9 6 4.03 6 9 6Z"/>
214+
</g>
215+
</svg>
216+
`;
217+
} else {
218+
eyeIcon.innerHTML = `
219+
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 18">
220+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1.933 10.909A4.357 4.357 0 0 1 1 9c0-1 4-6 9-6m7.6 3.8A5.068 5.068 0 0 1 19 9c0 1-3 6-9 6-.314 0-.62-.014-.918-.04M2 17 18 1m-5 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/>
221+
</svg>
222+
`;
223+
}
224+
}
225+
});
226+
</script>
227+
228+
229+
{% endblock extra_js %}

0 commit comments

Comments
 (0)