Added sign-in view and simple protected view
This commit is contained in:
@@ -112,7 +112,12 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
"DEFAULT_FILTER_BACKENDS": [
|
"DEFAULT_FILTER_BACKENDS": [
|
||||||
"django_filters.rest_framework.DjangoFilterBackend"
|
"django_filters.rest_framework.DjangoFilterBackend"
|
||||||
]
|
],
|
||||||
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||||
|
"users.authentication.JWTAuthentication",
|
||||||
|
"rest_framework.authentication.SessionAuthentication",
|
||||||
|
"rest_framework.authentication.BasicAuthentication",
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
APPEND_SLASH = False
|
APPEND_SLASH = False
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import jwt
|
||||||
|
from django.conf import settings
|
||||||
|
from rest_framework.authentication import BaseAuthentication
|
||||||
|
from rest_framework.exceptions import AuthenticationFailed
|
||||||
|
|
||||||
|
from users.models import Profile
|
||||||
|
|
||||||
|
|
||||||
|
class JWTAuthentication(BaseAuthentication):
|
||||||
|
def authenticate(self, request):
|
||||||
|
token = request.headers.get("Authorization", "").split("Bearer ")[-1]
|
||||||
|
|
||||||
|
if not token:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(
|
||||||
|
token, settings.SECRET_KEY, algorithms=["HS256"]
|
||||||
|
)
|
||||||
|
|
||||||
|
user = Profile.objects.get(login=payload["login"])
|
||||||
|
|
||||||
|
return (user, None)
|
||||||
|
except Profile.DoesNotExist:
|
||||||
|
raise AuthenticationFailed("Invalid token")
|
||||||
|
except jwt.ExpiredSignatureError:
|
||||||
|
raise AuthenticationFailed("Token has expired")
|
||||||
|
except jwt.InvalidTokenError:
|
||||||
|
raise AuthenticationFailed("Invalid token")
|
||||||
@@ -34,5 +34,8 @@ class Profile(models.Model):
|
|||||||
)
|
)
|
||||||
image = models.URLField(max_length=200, blank=True, null=True)
|
image = models.URLField(max_length=200, blank=True, null=True)
|
||||||
|
|
||||||
|
def is_authenticated(self):
|
||||||
|
return True
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.login
|
return self.login
|
||||||
|
|||||||
@@ -5,7 +5,16 @@ import users.views
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(
|
path(
|
||||||
"register",
|
"register",
|
||||||
users.views.register_user,
|
users.views.RegisterUserApiView.as_view(),
|
||||||
name="register",
|
name="register",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"sign-in",
|
||||||
|
users.views.SigninUserApiView.as_view(),
|
||||||
|
name="sign-in",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"protected-view",
|
||||||
|
users.views.ProtectedView.as_view(),
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import re
|
import re
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
import bcrypt
|
import bcrypt
|
||||||
|
import jwt
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import timezone
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import api_view
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from users.models import Profile
|
from users.models import Profile
|
||||||
from users.serializers import UserSerializer
|
from users.serializers import UserSerializer
|
||||||
@@ -12,8 +17,8 @@ MIN_PASSWORD_LEN = 6
|
|||||||
MAX_PASSWORD_LEN = 100
|
MAX_PASSWORD_LEN = 100
|
||||||
|
|
||||||
|
|
||||||
@api_view(["POST"])
|
class RegisterUserApiView(APIView):
|
||||||
def register_user(request):
|
def post(self, request):
|
||||||
serializer = UserSerializer(data=request.data)
|
serializer = UserSerializer(data=request.data)
|
||||||
|
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
@@ -53,10 +58,10 @@ def register_user(request):
|
|||||||
r"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,100}$"
|
r"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,100}$"
|
||||||
)
|
)
|
||||||
|
|
||||||
if not (
|
if not (bool(re.match(password_pattern, password))):
|
||||||
bool(re.match(password_pattern, password))
|
error = {
|
||||||
):
|
"message": "Your password does not meet our requirements"
|
||||||
error = {"message": "Your password does not meet our requirements"}
|
}
|
||||||
return Response(
|
return Response(
|
||||||
error,
|
error,
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
@@ -85,3 +90,44 @@ def register_user(request):
|
|||||||
return Response(profile, status=status.HTTP_201_CREATED)
|
return Response(profile, status=status.HTTP_201_CREATED)
|
||||||
|
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
class SigninUserApiView(APIView):
|
||||||
|
def post(self, request):
|
||||||
|
login = request.data.get("login")
|
||||||
|
password = request.data.get("password")
|
||||||
|
user = Profile.objects.filter(login=login).first()
|
||||||
|
|
||||||
|
if user is not None:
|
||||||
|
if not bcrypt.checkpw(
|
||||||
|
password.encode("utf-8"), user.password.encode("utf-8")
|
||||||
|
):
|
||||||
|
return Response(
|
||||||
|
{"error": "Invalid credentials"},
|
||||||
|
status=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return Response(
|
||||||
|
{"error": "Invalid credentials"},
|
||||||
|
status=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
)
|
||||||
|
|
||||||
|
token = jwt.encode(
|
||||||
|
{
|
||||||
|
"login": login,
|
||||||
|
"password": password,
|
||||||
|
"exp": timezone.now() + timedelta(hours=24),
|
||||||
|
},
|
||||||
|
settings.SECRET_KEY,
|
||||||
|
algorithm="HS256",
|
||||||
|
)
|
||||||
|
|
||||||
|
return Response({"token": token})
|
||||||
|
|
||||||
|
|
||||||
|
class ProtectedView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
user = request.user
|
||||||
|
return Response({"message": "Authenticated", "user": str(user)})
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ psycopg2-binary==2.9.9
|
|||||||
dj-database-url==2.1.0
|
dj-database-url==2.1.0
|
||||||
django-filter==23.5
|
django-filter==23.5
|
||||||
bcrypt==4.1.2
|
bcrypt==4.1.2
|
||||||
|
djangorestframework-jwt==1.11.0
|
||||||
|
|||||||
Reference in New Issue
Block a user