CBi analytics login register
Requirements backend
Django
Djangorestframework
Django-cors-headers
Knox
Cryptography
Boto3
Django_rest_passwordreset
Django-rest-knox
Backend
Create folder called backend
Cd backend
Python -m pip install virtualenv
Python -m venv venv
Creates virtual environment called venv
venv/scripts/activate
Its worth gitignor-ing your virtual environment
pip install Django djangorestframework django-cors-headers knox cryptography Jinja2 boto3 django-rest-passwordreset django-rest-knox
Django-admin startproject auth .
Not nested folder
Python manage.py startapp users
Add these to install apps in auth/settings .py
'rest_framework',
'corsheaders',
'users',
'knox',
'django_rest_passwordreset',
Add this to top of middleware
'corsheaders.middleware.CorsMiddleware',
Add allowed origins just below middleware
CORS_ALLOWED_ORIGINS = [
'http://localhost:5173',
]
Add this line just below that line
AUTH_USER_MODEL = 'users.CustomUser'
Just below that add this line
AUTHENTICATION_BACKENDS = [
# 'users.authback.EmailBackend',
"django.contrib.auth.backends.ModelBackend", # this line fixed my problem
]
Use these lines for the email settings
#the email settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASSWORD')
DEFAULT_FROM_EMAIL = 'CBI ANALYTICS'
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
Make sure templates is correct
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR/"templates"],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Configure authentication classes
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication',)
}
Then update urls.py
from django.contrib import admin
from django.urls import path, include
from knox import views as knox_views
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('users.urls')),
#path('api/auth/',include('knox.urls')),
path('logout/',knox_views.LogoutView.as_view(), name='knox_logout'),
path('logoutall/',knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
path('api/password_reset/',include('django_rest_passwordreset.urls', namespace='password_reset')),
]
In users app add this code to models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
from django_rest_passwordreset.signals import reset_password_token_created
from django.dispatch import receiver
from django.urls import reverse
from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives
from django.utils.html import strip_tags
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields ):
if not email:
raise ValueError('Email is a required field')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
email = models.EmailField(max_length=200, unique=True)
birthday = models.DateField(null=True, blank=True)
username = models.CharField(max_length=200, null=True, blank=True)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
@receiver(reset_password_token_created)
def password_reset_token_created(reset_password_token, *args, **kwargs):
sitelink = "http://localhost:5173/"
token = "{}".format(reset_password_token.key)
full_link = str(sitelink)+str("password-reset/")+str(token)
print(token)
print(full_link)
context = {
'full_link': full_link,
'email_adress': reset_password_token.user.email
}
html_message = render_to_string("backend/email.html", context=context)
plain_message = strip_tags(html_message)
msg = EmailMultiAlternatives(
subject = "Request for resetting password for {title}".format(title=reset_password_token.user.email),
body=plain_message,
from_email = "[email protected]",
to=[reset_password_token.user.email]
)
msg.attach_alternative(html_message, "text/html")
msg.send()
Also add this code to views.py
from django.shortcuts import render
from rest_framework import viewsets, permissions
from .serializers import *
from .models import *
from rest_framework.response import Response
from django.contrib.auth import get_user_model, authenticate
from knox.models import AuthToken
User = get_user_model()
class LoginViewset(viewsets.ViewSet):
permission_classes = [permissions.AllowAny]
serializer_class = LoginSerializer
def create(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
email = serializer.validated_data['email']
password = serializer.validated_data['password']
user = authenticate(request, email=email, password=password)
if user:
_, token = AuthToken.objects.create(user)
return Response(
{
"user": self.serializer_class(user).data,
"token": token
}
)
else:
return Response({"error":"Invalid credentials"}, status=401)
else:
return Response(serializer.errors,status=400)
class RegisterViewset(viewsets.ViewSet):
permission_classes = [permissions.AllowAny]
queryset = User.objects.all()
serializer_class = RegisterSerializer
def create(self,request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors,status=400)
class UserViewset(viewsets.ViewSet):
permission_classes = [permissions.IsAuthenticated]
queryset = User.objects.all()
serializer_class = RegisterSerializer
def list(self,request):
queryset = User.objects.all()
serializer = self.serializer_class(queryset, many=True)
return Response(serializer.data)
Create a urls.py file and add this code
from django.contrib import admin
from django.urls import path
from rest_framework.routers import DefaultRouter
from .views import *
router = DefaultRouter()
router.register('register', RegisterViewset, basename='register')
router.register('login', LoginViewset, basename='login')
router.register('users', UserViewset, basename='users')
urlpatterns = router.urls
Create a serializers.py file and add this code
from rest_framework import serializers
from .models import *
from django.contrib.auth import get_user_model
User = get_user_model()
class LoginSerializer(serializers.Serializer):
email = serializers.EmailField()
password = serializers.CharField()
def to_representation(self, instance):
ret = super().to_representation(instance)
ret.pop('password', None)
return ret
class RegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id','email','password')
extra_kwargs = { 'password': {'write_only':True}}
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
return user
Create auth_backend.py file and add this code
from django.contrib.auth import get_user_model
User = get_user_model()
class EmailAuthBackend:
def authenticate(self, request, email=None, password=None):
try:
user = User.objects.get(email=email)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
In the terminal do python manage.py makemigrations and then python manage.py migrate
Run the server
Python manage.py runserver and run some post requests
We are now finished with the backend
from django.contrib.auth import get_user_model
User = get_user_model()
class EmailAuthBackend:
def authenticate(self, request, email=None, password=None):
try:
user = User.objects.get(email=email)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Add this to apps.py file
from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'users'
Make sure admin.py looks like this
from django.contrib import admin
from .models import *
Register your models here.
admin.site.register(CustomUser)
In the terminal do python manage.py makemigrations and then python manage.py migrate
Run the server
Python manage.py runserver and run some post requests
We are now finished with the backend