Forgot password functionality build in Python / Django Rest Framework

Related tags

Djangoforgot-password
Overview

Password Recover

Recover password functionality with e-mail sender usign Django Email Backend

How to start project.

  • Create a folder in your machine
  • Create a virtual environment
    • python3 -m venv venv
  • Start the virtual environment
    • . venv/bin/activate (Linux)
    • venv/Scripts/Activate (Windows)
  • Inside your venv folder clone the project
    • git clone https://github.com/alexlopesbr/forgot-password.git
  • In your-new-folder/venv/forgot-password
    • pip install -r requirements.txt to install the project's dependencies
    • python manage.py migrate to generate your database
    • python3 manage.py createsuperuser to create the admin
    • python3 manage.py runserver to start the server
  • Open your browser and go to http://127.0.0.1:8000/admin/
  • Login with the admin credentials
    • Now you can see you user and some info in admin panel

Using the functionality

We have two POST requests:

{{localhost}}/core/user/forgot-password/ Send an e-mail with a link to recover the password.

body of the request:

    {
        "email": "email from you user created"
    }

{{localhost}}/core/user/change-forgotten-password/ Allows you to enter the new password.

body of the request:

    {
        "email": "email from you user created",
        "forgot_password_hash": "inside the redefine you passwod button sended to your email",
        "new_password": "set a new password"
    }

You can use Postman or Insomnia to test the requests.
Note: When you start your server the localhost generaly is http://127.0.0.1:8000/.


Some instructions and informations

root

setings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

BASE_URL = 'sandbox.com'

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'your-key'
EMAIL_PORT = 587
EMAIL_USE_TLS = True

First step, set some configures in settings.py. Don't forget to set the EMAIL_HOST_USER and the EMAIL_HOST_PASSWORD.


core

views.py

from core.models import User
from rest_framework.response import Response
from .services import send_forgot_password_email
from .exceptions import ForgotPasswordInvalidParams
from rest_framework.permissions import AllowAny
from rest_framework.decorators import action

@action(detail=False, methods=['post'], url_path='forgot-password', permission_classes=[AllowAny])
def forgot_password(self, request):
    if 'email' not in request.POST:
        raise ForgotPasswordInvalidParams
    send_forgot_password_email(request.POST['email'])
    return Response({'worked': True})

@action(detail=False, methods=['post'], url_path='change-forgotten-password', permission_classes=[AllowAny])
def change_forgotten_password(self, request):
    email = request.POST.get('email', None)
    forgot_password_hash = request.POST['forgot_password_hash']
    new_password = request.POST['new_password']
    User.change_password(email, forgot_password_hash, new_password)
    return Response({'worked': True})

Here we create a request called forgot-password to send an email with a link to change the password.
In this case, we are calling the send_forgot_password_email function. (see the function details below)

We also create a change-forgotten-password request to change the password. Here we need to send the email, the hash and the new password.

Obs. the hash is an inplicit parameter that is generated by the send_forgot_password_email function.

forgot_password_hash and new_password fields are set in core.models.py

services.py

from core.models import User
from emails.services import send_email_forgot_password
from core.exceptions import UserDoesNotExist
from django.utils import timezone
from datetime import timedelta
import re
import urllib.parse

def send_forgot_password_email(email):
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        raise UserDoesNotExist
    now = timezone.now()
    user.forgot_password_hash = re.sub(r'\D', '', str(now))
    user.forgot_password_expire = now + timedelta(hours=24)
    user.save()
    link = 'https://forgot-password.com/change-password?email=%s&hash=%s' % (
        urllib.parse.quote(user.email), user.forgot_password_hash)
    send_email_forgot_password(user.email, link)

In this function we gererate a hash with a simple timezone.now() that will be atribuate to forgot_password_hash. This will be our validator.
We also set the forgot_password_expire field with the same timezone.now() plus the timedelta of 24 hours. So we give to user 24 hours to change the password.
We can bring another informations like the name of the user, but we don't use it in this exemple.

In the send_email_forgot_password function we send the email with the link to change the password.


emails

services.py

from django.core.mail import EmailMessage
from django.conf import settings


def open_and_return(my_file):
    with open(settings.BASE_DIR + '/emails/templates/' + my_file, 'r', encoding="utf-8") as file:
        data = file.read()
    return data


def send_email_forgot_password(email, link):
    template = open_and_return("forgot-password.html").format(link)

    msg = EmailMessage(
        u'Email forgot password received',
        template,
        to=[email, ],
        from_email=settings.EMAIL_HOST_USER
    )

    msg.content_subtype = 'html'
    msg.send()

The last step is sending the email with the link to user to change the password.

open_and_return function opens the template and returns the content.
This template is in emails/templates/forgot-password.html and will be used to lets our email message prettier.
In template = open_and_return("forgot-password.html").format(link) we replace the link with the link that was setted in the send_forgot_password_email function.

More information about sending emails in Django documentation

Owner
alexandre Lopes
Graduated in Biological Sciences and now back end developer, I build API's in Python / Django Rest Framework but I confess that I love front end too.
alexandre Lopes
Updates redisearch instance with igdb data used for kimosabe

igdb-pdt Update RediSearch with IGDB games data in the following Format: { "game_slug": { "name": "game_name", "cover": "igdb_coverart_url",

6rotoms 0 Jul 30, 2021
Yet another Django audit log app, hopefully the simplest one.

django-easy-audit Yet another Django audit log app, hopefully the easiest one. This app allows you to keep track of every action taken by your users.

Natán 510 Jan 02, 2023
Full-text multi-table search application for Django. Easy to install and use, with good performance.

django-watson django-watson is a fast multi-model full-text search plugin for Django. It is easy to install and use, and provides high quality search

Dave Hall 1.1k Dec 22, 2022
A Django app that allows visitors to interact with your site as a guest user without requiring registration.

django-guest-user A Django app that allows visitors to interact with your site as a guest user without requiring registration. Largely inspired by dja

Julian Wachholz 21 Dec 17, 2022
Automated image processing for Django. Currently v4.0

ImageKit is a Django app for processing images. Need a thumbnail? A black-and-white version of a user-uploaded image? ImageKit will make them for you.

Matthew Dapena-Tretter 2.1k Jan 04, 2023
Loguru is an exceeding easy way to do logging in Python

Django Easy Logging Easy Django logging with Loguru Loguru is an exceeding easy way to do logging in Python. django-easy-logging makes it exceedingly

Neutron Sync 8 Oct 17, 2022
Get inside your stronghold and make all your Django views default login_required

Stronghold Get inside your stronghold and make all your Django views default login_required Stronghold is a very small and easy to use django app that

Mike Grouchy 384 Nov 23, 2022
A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.

django-versatileimagefield A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for creat

Jonathan Ellenberger 490 Dec 13, 2022
A multiprocessing distributed task queue for Django

A multiprocessing distributed task queue for Django Features Multiprocessing worker pool Asynchronous tasks Scheduled, cron and repeated tasks Signed

Ilan Steemers 1.7k Jan 03, 2023
A pickled object field for Django

django-picklefield About django-picklefield provides an implementation of a pickled object field. Such fields can contain any picklable objects. The i

Gintautas Miliauskas 167 Oct 18, 2022
Django Serverless Cron - Run cron jobs easily in a serverless environment

Django Serverless Cron - Run cron jobs easily in a serverless environment

Paul Onteri 41 Dec 16, 2022
Transparently use webpack with django

Looking for maintainers This repository is unmaintained as I don't have any free time to dedicate to this effort. If you or your organisation are heav

Owais Lone 2.4k Jan 06, 2023
Analytics services for Django projects

django-analytical The django-analytical application integrates analytics services into a Django project. Using an analytics service with a Django proj

Jazzband 1.1k Dec 31, 2022
Per object permissions for Django

django-guardian django-guardian is an implementation of per object permissions [1] on top of Django's authorization backend Documentation Online docum

3.3k Jan 04, 2023
Alt1-compatible widget host for RuneScape 3

RuneKit Alt1-compatible toolbox for RuneScape 3, for Linux and macOS. Compatibility macOS installation guide Running This project use Poetry as packag

Manatsawin Hanmongkolchai 75 Nov 28, 2022
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 06, 2023
A CTF leaderboard for the submission of flags during a CTF challenge. Built using Django.

🚩 CTF Leaderboard The goal of this project is to provide a simple web page to allow the participants of an CTF to enter their found flags. Also the l

Maurice Bauer 2 Jan 17, 2022
Code coverage measurement for Python

Coverage.py Code coverage testing for Python. Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and

Ned Batchelder 2.3k Jan 05, 2023
Send push notifications to mobile devices through GCM or APNS in Django.

django-push-notifications A minimal Django app that implements Device models that can send messages through APNS, FCM/GCM and WNS. The app implements

Jazzband 2k Dec 26, 2022
The friendly PIL fork (Python Imaging Library)

Pillow Python Imaging Library (Fork) Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lund

Pillow 10.4k Jan 03, 2023