Commit c221c203 authored by Ilham Maulana's avatar Ilham Maulana 💻

feat: reset password

parent 7fff24be
...@@ -168,6 +168,16 @@ STORAGES = { ...@@ -168,6 +168,16 @@ STORAGES = {
}, },
} }
# EMAIL CONFIGS
# smptp using etheral email mock smptp server
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.ethereal.email"
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = "jaquan.ohara41@ethereal.email"
EMAIL_HOST_PASSWORD = "83VFaB6ZGSzy72D24T"
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
......
...@@ -19,7 +19,10 @@ from django.contrib import admin ...@@ -19,7 +19,10 @@ from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib.auth.views import LogoutView from django.contrib.auth.views import (
PasswordResetConfirmView,
PasswordResetCompleteView,
)
from dashboard.views import UpcomingLoanView, OverduedLoanView from dashboard.views import UpcomingLoanView, OverduedLoanView
from users.views import ( from users.views import (
...@@ -42,11 +45,26 @@ urlpatterns = [ ...@@ -42,11 +45,26 @@ urlpatterns = [
path("auth/login/", LibrarianLoginView.as_view(), name="librarian_login"), path("auth/login/", LibrarianLoginView.as_view(), name="librarian_login"),
path("auth/logout/", LibrarianLogoutView.as_view(), name="librarian_logout"), path("auth/logout/", LibrarianLogoutView.as_view(), name="librarian_logout"),
path("auth/sign-up/", LibrarianSignUpView.as_view(), name="librarian_logout"), path("auth/sign-up/", LibrarianSignUpView.as_view(), name="librarian_logout"),
# password reset
path( path(
"auth/forgot-password/", "password-reset/",
LibrarianResetPassword.as_view(), LibrarianResetPassword.as_view(),
name="reset_password", name="reset_password",
), ),
path(
"password-reset-confirm/<uidb64>/<token>/",
PasswordResetConfirmView.as_view(
template_name="password/password_reset_confirm.html"
),
name="password_reset_confirm",
),
path(
"password-reset-complete/",
PasswordResetCompleteView.as_view(
template_name="password/password_reset_complete.html"
),
name="password_reset_complete",
),
# api # api
path("api/v1/", include("api.urls"), name="API_V1"), path("api/v1/", include("api.urls"), name="API_V1"),
# 3rd party # 3rd party
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<p class="my-2"> <p class="my-2">
Don't have an account? <a href="/auth/sign-up">Sign Up</a> Don't have an account? <a href="/auth/sign-up">Sign Up</a>
</p> </p>
<a href="/auth/forgot-password/" class="my-2">Forgot password</a> <a href="/password-reset/" class="my-2">Forgot password</a>
</div> </div>
</form> </form>
</main> </main>
......
{% extends "base.html" %} {% block content %}
<main
style="min-height: 100vh"
class="h-100 bg-body-secondary d-flex justify-content-center align-items-center"
>
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="m-4 alert alert-info">
Your password has been set.
</div>
<a class="mx-4 mb-4 btn btn-primary rounded-pill" href="/auth/login/">Login Here</a>
</div>
</main>
{% endblock content %}
\ No newline at end of file
{% extends "base.html" %} {% block content %}
<main
style="min-height: 100vh"
class="h-100 bg-body-secondary d-flex justify-content-center align-items-center"
>
<div class="form-content">
<div style="max-width: 25vw;" class="row justify-content-center">
<div>
{% if validlink %}
<div class="card shadow-lg border-0 rounded-4 mt-0 mb-3">
<div class="px-4 justify-content-center">
<h3 class="font-weight-light my-4 text-center">Reset Your Password</h3>
</div>
{% if form.errors %}
<div class="mx-4 alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<span>Please try again</span>
</div>
{% endif %}
<div class="card-body">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_new_password1">New Password</label>
<input type="password" name="new_password1" autocomplete="new-password" class="form-control" required id="id_new_password1" placeholder="Enter password"/>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_new_password2">New Password Confirmation</label>
<input type="password" name="new_password2" autocomplete="new-password" required id="id_new_password2" class="form-control" placeholder="Confirm password"/>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group my-4">
<button type="submit" class="col-md-12 btn btn-primary rounded-pill" id="reset">Reset Password</button>
</div>
</div>
</div>
</form>
</div>
</div>
{% else %}
<div class="alert alert-warning">
The password reset link was invalid, possibly because it has already been used.
Please request a new password reset.
</div>
{% endif %}
</div>
</div>
</div>
</main>
{% endblock content %}
\ No newline at end of file
Password Reset Confirm From Django
To initiate the password reset process for your {{ user.email }} Django Registration/Login App Account, click the link below:
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
If clicking the link above doesn't work, please copy and paste the URL in a new browser
window instead.
Sincerely,
The Developer, Ilham Maulana Pratama
\ No newline at end of file
...@@ -4,6 +4,7 @@ from django.contrib.auth import logout ...@@ -4,6 +4,7 @@ from django.contrib.auth import logout
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.contrib.auth.views import LoginView, PasswordResetView from django.contrib.auth.views import LoginView, PasswordResetView
from django.contrib.messages.views import SuccessMessageMixin
from users.models import Librarian, Member from users.models import Librarian, Member
from users.forms import UserForm, User, LoginForm, SignUpForm, ForgotPasswordForm from users.forms import UserForm, User, LoginForm, SignUpForm, ForgotPasswordForm
...@@ -201,6 +202,14 @@ class LibrarianSignUpView(generic.FormView): ...@@ -201,6 +202,14 @@ class LibrarianSignUpView(generic.FormView):
return self.form_invalid(form) return self.form_invalid(form)
class LibrarianResetPassword(PasswordResetView): class LibrarianResetPassword(SuccessMessageMixin, PasswordResetView):
form_class = ForgotPasswordForm form_class = ForgotPasswordForm
template_name = "librarians/forgot_password.html" template_name = "password/password_reset.html"
email_template_name = "password/password_reset_email.html"
success_message = (
"We've emailed you instructions for setting your password, "
"if an account exists with the email you entered. You should receive them shortly."
" If you don't receive an email, "
"please make sure you've entered the address you registered with, and check your spam folder."
)
success_url = "/password-reset-complete/"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment