From 23c3918697710dabf2bf3d26abcbd664ecf881b6 Mon Sep 17 00:00:00 2001 From: Ian Andwati Date: Wed, 6 Mar 2024 00:38:41 +0300 Subject: [PATCH] completed authentication serializers --- Pipfile | 2 +- Pipfile.lock | 11 ++++++- authentication/__init__.py | 0 authentication/admin.py | 3 ++ authentication/apps.py | 6 ++++ authentication/backends.py | 26 +++++++++++++++ authentication/migrations/__init__.py | 0 authentication/models.py | 3 ++ authentication/serializers.py | 32 +++++++++++++++++++ authentication/tests.py | 3 ++ authentication/views.py | 3 ++ ..._brand_remove_product_supplier_and_more.py | 27 ++++++++++++++++ store/settings.py | 4 +++ 13 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 authentication/__init__.py create mode 100644 authentication/admin.py create mode 100644 authentication/apps.py create mode 100644 authentication/backends.py create mode 100644 authentication/migrations/__init__.py create mode 100644 authentication/models.py create mode 100644 authentication/serializers.py create mode 100644 authentication/tests.py create mode 100644 authentication/views.py create mode 100644 products/migrations/0002_remove_product_brand_remove_product_supplier_and_more.py diff --git a/Pipfile b/Pipfile index 69c3abc..0423293 100644 --- a/Pipfile +++ b/Pipfile @@ -7,8 +7,8 @@ name = "pypi" django = "*" python-dotenv = "*" djangorestframework = "*" -django-rest-swagger = "*" drf-yasg = "*" +pyjwt = "*" [dev-packages] black = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 20d57a6..2d7373d 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "e809082b9f93f07ff5ab032b2b74852d5953598169a20d6a35c8308b6c2f14ab" + "sha256": "ecb5c24f0cd1dff8305c31b43f5cfdc663cf0435e9e672c44269060b890308fb" }, "pipfile-spec": 6, "requires": { @@ -288,6 +288,15 @@ "markers": "python_version >= '3.7'", "version": "==23.2" }, + "pyjwt": { + "hashes": [ + "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de", + "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==2.8.0" + }, "python-dotenv": { "hashes": [ "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", diff --git a/authentication/__init__.py b/authentication/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/admin.py b/authentication/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/authentication/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/authentication/apps.py b/authentication/apps.py new file mode 100644 index 0000000..c65f1d2 --- /dev/null +++ b/authentication/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AuthenticationConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "authentication" diff --git a/authentication/backends.py b/authentication/backends.py new file mode 100644 index 0000000..a41fc08 --- /dev/null +++ b/authentication/backends.py @@ -0,0 +1,26 @@ +import jwt +from django.conf import settings +from django.contrib.auth.models import User +from rest_framework import authentication, exceptions + + +class JWTAuthentication(authentication.BaseAuthentication): + def authenticate(self, request): + + auth_data = authentication.get_authorization_header(request) + + if not auth_data: + return None + + prefix, token = auth_data.decode("utf-8").split(" ") + + try: + payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms="HS256") + user = User.objects.get(username=payload["username"]) + return (user, token) + except jwt.DecodeError as err: + raise exceptions.AuthenticationFailed("Your token is invalid, please login") + except jwt.ExpiredSignatureError as err: + raise exceptions.AuthenticationFailed("Your token is expired, login") + + return super().authenticate(request) diff --git a/authentication/migrations/__init__.py b/authentication/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/models.py b/authentication/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/authentication/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/authentication/serializers.py b/authentication/serializers.py new file mode 100644 index 0000000..218103d --- /dev/null +++ b/authentication/serializers.py @@ -0,0 +1,32 @@ +from django.contrib.auth.models import User +from rest_framework import serializers + + +class UserSerializer(serializers.ModelSerializer): + password = serializers.CharField(max_length=65, min_length=8, write_only=True) + email = serializers.EmailField(max_length=255) + first_name = serializers.CharField(max_length=255) + last_name = serializers.CharField(max_length=255) + + class Meta: + model = User + fields = ["username", "first_name", "last_name", "email", "password"] + + def validate(self, attrs): + + email = attrs.get("email", "") + if User.objects.filter(email=email).exists(): + raise serializers.ValidationError({"error": "Email is already in use"}) + return super().validate(attrs) + + def create(self, validated_data): + return User.objects.create_user(**validated_data) + + +class LoginSerializer(serializers.ModelSerializer): + password = serializers.CharField(max_length=65) + username = serializers.CharField(max_length=255) + + class Meta: + model = User + fields = ["username", "password"] diff --git a/authentication/tests.py b/authentication/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/authentication/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/authentication/views.py b/authentication/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/authentication/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/products/migrations/0002_remove_product_brand_remove_product_supplier_and_more.py b/products/migrations/0002_remove_product_brand_remove_product_supplier_and_more.py new file mode 100644 index 0000000..96672eb --- /dev/null +++ b/products/migrations/0002_remove_product_brand_remove_product_supplier_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.3 on 2024-03-05 21:08 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("products", "0001_initial"), + ] + + operations = [ + migrations.RemoveField( + model_name="product", + name="brand", + ), + migrations.RemoveField( + model_name="product", + name="supplier", + ), + migrations.DeleteModel( + name="Brand", + ), + migrations.DeleteModel( + name="Supplier", + ), + ] diff --git a/store/settings.py b/store/settings.py index 6bf1157..319f060 100644 --- a/store/settings.py +++ b/store/settings.py @@ -55,10 +55,14 @@ THIRD_PARTY_APPS = [ LOCAL_APPS = [ "products.apps.ProductsConfig", + "authentication.apps.AuthenticationConfig", ] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS +# JWT settings +JWT_SECRET_KEY = os.environ.get("JWT_SECRET_KEY") + MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware",