Even after dispatching, CSRF token won't work - python

So I followed the instructions from the answers on this thread:
#csrf_exempt does not work on generic view based class
However, when I send POST requests via Postman, it still keeps throwing 403 error and I wonder what I am missing here. I tried the last answer(using braces.views and CsrfExemptMixin) as well and it still wouldn't work. Below is my code so far
import json
import jwt
from psr.settings import SECRET_KEY
from django.http import HttpResponse, JsonResponse
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth import views as auth_views
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from braces.views import CsrfExemptMixin
from .models import User
class LoginView(auth_views.LoginView):
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(LoginView, self).dispatch(request, *args, **kwargs)
def post(self, request):
form = AuthenticationForm(data = request.POST)
if form.is_valid():
user = authenticate(email=request.POST['email'], password=request.POST['password'])
if user is not None:
messages.add_message(request, messages.SUCCESS, "Welcome back, {}".format(user))
login(request, user)
token = jwt.encode({'id': user.id}, SECRET_KEY, algorithm='HS256').decode('utf-8')
return JsonResponse({'token': token}, status=200)
Am I missing something here?
Thanks a lot in advance!

Related

How to verify Shopify webhook in Django?

How can I verify the incoming webhook from Shopify? Shopify provides a python implementation (of Flask), but how can I do it in Django/DRF?
Set these two variables in the settings.py file
# settings.py
SHOPIFY_HMAC_HEADER = "HTTP_X_SHOPIFY_HMAC_SHA256"
SHOPIFY_API_SECRET = "5f6b6_my_secret"
Then, create a verify webhook function that accepts the Django request as it's parameter
# utils.py
import base64
import hashlib
import hmac
from django.conf import settings
from django.core.handlers.wsgi import WSGIRequest
def verify_shopify_webhook(request: WSGIRequest):
shopify_hmac_header = request.META.get(settings.SHOPIFY_HMAC_HEADER)
encoded_secret = settings.SHOPIFY_API_SECRET.encode("utf-8")
digest = hmac.new(
encoded_secret,
request.body,
digestmod=hashlib.sha256,
).digest()
computed_hmac = base64.b64encode(digest)
return hmac.compare_digest(computed_hmac, shopify_hmac_header.encode("utf-8"))
Then, create a view that accepts the incoming webhook and use the verify_shopify_webhook(...) function to verify the request.
# views.py
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from .utils import verify_shopify_webhook
#method_decorator(csrf_exempt, name="dispatch")
class ShopifyWebhookView(View):
def post(self, request, *args, **kwargs):
verified = verify_shopify_webhook(request=request)
return HttpResponse(status=200 if verified else 403)
If you're using Django REST Framework, you can also use APIView as
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .utils import verify_shopify_webhook
class ShopifyWebhookView(APIView):
def post(self, request, *args, **kwargs):
verified = verify_shopify_webhook(request=request)
return Response(status=200 if verified else 403)

IntegrityError at /signup UNIQUE constraint failed: auth_user.username ---> In django

When I click on sign in button I get integrity error!! I have checked in my admin site and all users are properly visible which I had signed up. But when I click sign in button with entries already registered in admin, my code crashes and gives integrity error!!
views.py:
from django.http import HttpResponse
from django.shortcuts import redirect, render , HttpResponse
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth import authenticate , login
# Create your views here.
def home(request):
return render(request,"authentication/index.html")
def signup(request):
if request.method=="POST":
username=request.POST.get('username')
fname=request.POST.get('fname')
lname=request.POST.get('lname')
email=request.POST.get('email')
pass1=request.POST.get('pass1')
pass2=request.POST.get('pass2')
myuser=User.objects.create_user(username,email,pass1) #creating user
myuser.first_name=fname
myuser.last_name=lname
myuser.save()
messages.success(request,"Your account has been successfuly created")
return redirect('/signin')
return render(request,"authentication/signup.html")
def signin(request):
if request.method=='POST':
username=request.POST.get('username')
pass1=request.POST.get('pass1')
user=authenticate(username=username,password=pass1)
if user is not None:
login(request,user)
return render(request,"authentication/index.html")
else:
messages.error(request,"Bad credentials")
redirect('home')
return render(request,"authentication/signin.html")
def signout(request):
pass

Django class based views get post data and send response

Working on an Api I wanted to give class based views in Django a go.
This is what I got so far:
urls.py
from django.conf.urls import url
from .api import Api
urlpatterns = [
url(r'^', Api.as_view())
]
api.py
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View
class Api(View):
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
super(Api, self).dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return HttpResponse("result")
def get(self, request):
return HttpResponse("result")
When calling this code from Postman I keep getting 2 issues:
Post data
In postman I have set a value in the Post headers but when I use the debugger to check the POST data it just isn't there.
Return HttpResponse
I keep getting the error The view api.api.Api didn't return an HttpResponse object. It returned None instead.
When I change the post method to a get method and send a get request with Postman I get the same result.
You need to do:
return super(Api, self).dispatch(request, *args, **kwargs)
You're not returning anything, and a function returns None by default.
Also, you probably want your url as r'^$'

How to test Django redirect from view class

I'm learning Django atm and I am stuck with creating a simple test case.
How I can test the following view? If the user is already logged in it redirects him to list view.
from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import AuthenticationForm
from django.views.generic import TemplateView
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
class LoginView(TemplateView):
"""
Base class for client area login.
"""
def get(self, request, *args, **kwargs):
"""
Display login form, only if user is not yet authenticated.
Otherwise redirect to tickets index.
:param request:
:param args:
:param kwargs:
:return:
"""
if request.user.is_authenticated():
return redirect(reverse('tickets:index'))
form = AuthenticationForm()
return render(request, 'login.html', {'form': form})
So far the test I have created looks like this:
from django.test import TestCase, RequestFactory
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User, AnonymousUser
from app.account.views import LoginView
class TestLoginForm(TestCase):
def setUp(self):
"""
Set up environment
:return:
"""
self.user = User.objects.create_user(username="test", password="test123", email="test#gmail.com")
self.factory = RequestFactory()
def tearDown(self):
"""
Clean created user object
:return:
"""
self.user.delete()
self.factory = None
def test_login_form_redirect(self):
"""
Test login redirect
:return:
"""
request = self.factory.get(reverse('account:login'))
request.user = AnonymousUser()
view = LoginView()
response = view.get(request=request)
self.assertEqual(response.status_code, 200)
request.user = self.user
response = view.get(request=request)
self.assertRedirects(response, expected_url=reverse('tickets:index'), status_code=302, target_status_code=200)
The first assertation passed, but the second where the user should be redirected if already has logged in throws this error
AttributeError: 'HttpResponseRedirect' object has no attribute 'client'
What am I doing wrong?
Ok I have managed to make successful test case, with following code
def test_login_form_redirect(self):
"""
Test login redirect
:return:
"""
self.client.logout()
response = self.client.get(reverse('account:login'))
self.assertEqual(response.status_code, 200)
self.assertTrue(self.client.login(username='test', password='test123'))
response = self.client.get(reverse('account:login'))
self.assertRedirects(response, expected_url=reverse('tickets:index'), status_code=302, target_status_code=200)

Testing authentication in Django Rest Framework Views -- Cannot authenticate when testing

After struggling mightily with this issue, I've come asking for a bit of help. I'm writing a test for a Django Rest Framework view, testing whether or not I can access the data whilst authenticated, and not. However, even when I'm authenticated, I still get 401 UNAUTHORIZED every time. Here's my tests:
from django.test import TestCase
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
from rest_framework.test import APIRequestFactory, APIClient
from apps.core import models, admin
from apps.rest import views
class TestAPIViews(TestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.client = APIClient()
self.user = User.objects.create_user('testuser', email='testuser#test.com', password='testing')
self.user.save()
token = Token.objects.create(user=self.user)
token.save()
def _require_login(self):
self.client.login(username='testuser', password='testing')
def test_ListAccounts_not_authenticated(self):
request = self.factory.get('/accounts/')
view = views.ListAccounts.as_view()
response = view(request)
self.assertEqual(response.status_code, 401,
'Expected Response Code 401, received {0} instead.'.format(response.status_code))
def test_ListAccounts_authenticated(self):
self.client._require_login()
print(self.user.is_authenticated()) # returns True
request = self.factory.get('/accounts/')
view = views.ListAccounts.as_view()
response = view(request)
self.assertEqual(response.status_code, 200,
'Expected Response Code 200, received {0} instead.'.format(response.status_code))
And here is the code for my DRF View:
from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from django.db.models import Q
from apps.core import serializers, models
from apps.rest.permissions import IsAccountOwner
from rest_framework.views import APIView
from rest_framework import status, authentication, generics
from rest_framework.response import Response
from rest_framework.authtoken.models import Token
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from apps.core import serializers, models
'''
Auth Mixin for Account Admin Access
'''
class AuthMixin:
authentication_classes = (authentication.TokenAuthentication,
authentication.SessionAuthentication)
permission_classes = (IsAuthenticated,)
class GenericList(AuthMixin, generics.ListAPIView):
def get_queryset(self):
# Stubbed out - doing nothing special right now
qs = self.model.objects.filter()
return qs
class ListAccounts(GenericList):
model = models.Account
serializer_class = serializers.AccountSerializer
As one can see, I'm calling login in the test_ListAccounts_authenticated, and then printing out whether or not I'm authenticated (Which returns True), but I get a 401 UNAUTHORIZED Error no matter what. Anything I'm missing? Thanks in advance.
Instead of calling self.factory.get(), call self.client.get().
I'm guessing self.client.login has no effect on self.factory.

Categories

Resources