I have my API and here I developed login and logout view. Now I want to write pytests and I have a problem, idk how to create fixture where I can make my user authorized and set some id in session(this is required for the logout).
I create new_user via fixture(to avoid working with my db).
views
#csrf_exempt
def login(request):
if request.method == "POST":
data = json.loads(request.body.decode('utf-8'))
if not is_data_valid_for_login(data):
return HttpResponseBadRequest()
user = authenticate(email=data["email"], password=data["password"])
if user:
auth_login(request, user)
response = HttpResponse(status=200, content_type='application/json')
request.session['id'] = user.id
return response
return HttpResponseBadRequest()
return HttpResponseBadRequest()
#csrf_exempt
def logout(request):
if request.method == "GET":
auth_logout(request)
response = HttpResponse(status=200)
if 'id' in request.session:
del request.session['id']
return response
return HttpResponseBadRequest
pytest
import pytest
from user.models import User
PASSWORD = "testPassword"
#pytest.fixture()
def user():
return User.create(first_name="Name", last_name="Last", email="test#test.com", password=PASSWORD)
Related
This is my page url within the urls.py file:
path('login/',views.login_view, name="login"),
This is my page view with the views.py file:
def login_view(request):
if request.method == "POST":
user_name = request.POST.get("username")
pass_word = request.POST.get("password")
user = authenticate(request, username=user_name, password=pass_word)
# print("user1 -->", user)
if user is not None:
# print("user-->",user)
login(request, user)
return render(request, "index.html")
else:
return render(request,"http://127.0.0.1:8000/login")
else:
# return render(request, "order.html")
return render(request, "login.html")
The error I am getting is:
TypeError at /login/logincheck/login() missing 1 required positional
argument: 'user'
first create a forms.py file:
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(max_length=63)
password = forms.CharField(max_length=63, widget=forms.PasswordInput)
your views.py should seem like this:
from django.contrib.auth import login, authenticate
from . import forms
def login_view(request):
form = forms.LoginForm()
message = ''
if request.method == 'POST':
form = forms.LoginForm(request.POST)
if form.is_valid():
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password'],
)
if user is not None:
login(request, user)
message = f'Hello {user.username}! You have been logged in'
else:
message = 'Login failed!'
return render(
request, 'authentication/login.html', context={'form': form, 'message': message})
Just to add to #enes islam's approach... It's okay with what he posted as his answer but according to your project you have another view in your views.py file called login so maybe it's using that view and not the django login method you imported.
# You have this import line here
from django.contrib.auth import authenticate, logout, login
# But I noticed further down you have a defined login method
def login(request): # -> rename this method name to loginDjano or another name.
return render(request, "login.html")
That defined method is what is really being called here... So I'd suggest you delete or rename that method then go ahead and use that line again.
if user is not None:
# Remember to pass both request and user objects to this login method
login(request, user)
message = f'Hello {user.username}! You have been logged in'
else:
message = 'Login failed!'
Ideally, that should work.
I am using the django-email-verification app and I had to change how a User is signed up but I left the login authentication part the same. Every time I try to login it does not allow me to sign in and says that the credentials are wrong. Also I used emails as usernames. I'm thinking its the:
user = auth.authenticate(username=request.POST['username'], password=request.POST['password'])
that needs to be changed. Please how do I fix the login?
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib import auth
from django.contrib.auth import get_user_model
from django_email_verification import sendConfirm
def signup(request):
if request.method == 'POST':
if request.POST['pass1'] == request.POST['pass2']:
try:
user = User.objects.get(username=request.POST['username'])
return render(request, 'accounts/signup.html', {'error': 'Email is already registered'})
except User.DoesNotExist:
'''user = User.objects.create_user(request.POST['username'], password=request.POST['pass1'])
auth.login(request, user)'''
user = get_user_model().objects.create(username=request.POST['username'], password=request.POST['pass1'], email=request.POST['username'])
sendConfirm(user)
return redirect('home')
else:
return render(request, 'accounts/signup.html', {'error': 'Passwords must match'})
else:
return render(request, 'accounts/signup.html')
def login(request):
if request.method == 'POST':
user = auth.authenticate(username=request.POST['username'], password=request.POST['password'])
if user is not None:
auth.login(request, user)
return redirect('home')
else:
return render(request, 'accounts/login.html',{'error':'username or password is incorrect.'})
else:
return render(request, 'accounts/login.html')
def logout(request):
if request.method == 'POST':
auth.logout(request)
return redirect('home')
The problem is not with authenticating, but with creating the user. Passwords are normally hashed. The .create(…) function [Django-doc] will not hash these, you can make use of .create_user(…) [Django-doc] instead:
user = get_user_model().objects.create_user(
username=request.POST['username'],
password=request.POST['pass1'],
email=request.POST['username']
)
The .create_user(…) function is a function the manager of the user model normally should provide. This will for (most) user models store the hash of the password in the database.
I am writing a middleware to track user activity by writing it to a file; the pages visited by him, the buttons clicked and so on and so forth. To test my middleware for now I am just writing a message to the file. But for some reason the message is being written twice to the file. And I am on django 1.11
Here is my middleware:
from django.http import HttpResponse
import datetime
class TodoappMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
f = open("--my file path--", 'a')
date_and_time = datetime.datetime.now()
f.write('\n')
f.write(str(date_and_time))
f.write('\tMiddleware successfully executed\n')
f.close()
response = self.get_response(request)
return response
EDIT: Got to know that redirect causes middleware to execute twice.
Here are my views which use HttpResponseRedirect
def login_user(request):
if request.method == 'POST':
login_form = Login(request.POST)
if login_form.is_valid():
email = login_form.cleaned_data['email']
password = login_form.cleaned_data['password']
User.objects.get(email=email)
user = authenticate(email=email, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('dashboard'))
else:
return HttpResponse("<h2>Waiting for admin to authenticate you</h2>")
else:
return render(request, 'registration/login.html', {'errors': login_form.errors})
return render(request, 'registration/login.html', {'form': Login()})
#login_required
def logout_user(request):
logout(request)
return redirect('login_user')
What changes do I need to do so that the middleware is executed only once ?
i have a simple chat application where i've customize the Authentication back end to use only the name. So far it is working and the users is logged in using Django login().
Now i have a problem with assign a user where this Error came up and cus the rest of the app to stop:
ValueError: Cannot assign "<SimpleLazyObject:
<django.contrib.auth.models.AnonymousUser
object at 0x7f7db7b71e80>>": "PChat.user" must be a "User" instance.
View.py
from chatbot import settings
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse,HttpResponseRedirect
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate, login
from Pchat.models import PChat
from django.contrib.auth.models import User
#csrf_exempt
def P_home(request):
context= locals()
template= 'P_home.html'
return render(request,template,context)
#csrf_exempt
def P_chat(request):
context= locals()
template= 'P_chat.html'
return render(request,template,context)
#csrf_exempt
def LogIIn(request):
if request.method == "POST":
name = request.POST.get('param1')
user = authenticate(username=name)
login(request, user)
return HttpResponse("OK")
#csrf_exempt
def Post(request):
if request.method == "POST":
msg = request.POST.get('param1')
if request.user.is_authenticated():
c = PChat(user=request.user, message=msg)
c.save()
return JsonResponse({ 'msg': msg, 'user': c.request.user })
else:
return HttpResponse("Account None")
models.py
from django.db import models
from django.db import models
from django.contrib.auth.models import User
class PChat(models.Model):
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User)
message = models.CharField(max_length=200)
def __unicode__(self):
return self.message
auth_backend.py
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class PasswordlessAuthBackend(ModelBackend):
"""Log in to Django without providing a password."""
def authenticate(self, username=None):
try:
return User.objects.get(username=username)
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
OK, there are several errors on your code:
1) In P_home and P_chat you are using locals(), that's not recommended. You must avoid that whenever possible. You need to be explicit with data passed to the context dictionary.
2) In LogIIn view you must call login function when user is not None. [1]
3) The final error is in Post view, you must ask first wheter request.user is authenticated or not using request.user.is_authenticated() function. If the user is authenticated, then request.user is a normal User instance in other case its going to be an AnonymousUser, they both are different things. The field user in PChat model is expecting an User instead an AnonymousUser instance.
[1] https://docs.djangoproject.com/en/1.11/topics/auth/default/#how-to-log-a-user-in
You have problem in line:
c = PChat(user=request.user, message=msg)
request.user is not a User object. Firstly check request.user is actual user or not.
if request.user.is_authenticated():
c = PChat(user=request.user, message=msg)
c.save()
return JsonResponse({ 'msg': msg, 'user': c.user.username })
else:
return JsonResponse({ 'msg': 'user is not logged in' })
Edit
def Post(request):
if request.method == "POST":
msg = request.POST.get('param1')
if request.user.is_authenticated():
c = PChat(user=request.user, message=msg)
c.save()
return JsonResponse({ 'msg': msg, 'user': c.request.user })
return HttpResponse("Account None")
I have simple python flask app with flask-login implemented. I have two functions to load template called first.html and second.html both of them are protected by a #login_required decorator. Below is the code I have written
#!/usr/bin/python
from app import app
from flask import render_template,request,redirect,abort
from flask_login import login_required,url_for,login_user,logout_user,LoginManager
from app.models.models import Users
import md5
from itsdangerous import URLSafeTimedSerializer
loginManager = LoginManager()
loginManager.init_app(app)
loginManager.login_view = 'signin'
loginManager.login_message = 'Please log in'
#loginManager.user_loader
def load_user(name):
user = Users.query.get(name)
return user
#loginManager.token_loader
def load_token(token):
print 'In Token Loader'
serializer = URLSafeTimedSerializer(app.secret_key)
data = serializer.loads(token)
username = data[0]
user = Users.query.get(name)
print user
return user
#app.route('/logout')
def logout():
print 'executing logout'
logout_user()
return render_template('login.html')
#app.route('/login',methods=['GET','POST'])
def signin():
if request.method == 'GET':
return render_template('login.html')
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
salted_password = password + app.secret_key
hashedpassword = md5.new(salted_password).hexdigest()
user = Users.query.filter(Users.username == username).first()
if user == None:
return render_template('login.html')
storedPass = user.password
if storedPass == hashedpassword:
login_user(user, remember=True)
nex = request.args.get('next')
return redirect(nex or url_for('first'))
return render_template('login.html')
#app.route('/first')
#login_required
def first():
return render_template('first.html')
#app.route('/second')
#login_required
def second():
return render_template('second.html')
Now I access http://locahost:5000/login and login view is loaded. I entered the valid user and password which is authenticated successfully and gets a redirect to url_for('first')
Since first function is decorated with #login_required I am getting the login page again. As per my understanding from documentation, #token_loader called will be called and it handles the token and loads the first.html but this is not happening and login view is loaded again.
If i remove the #login_required decorator from first function, the the first.html is loaded.
I am missing something in invoking the token validation in my code and I am not sure what it is.
My User data model class looks like below
#!/usr/bin/python
from app import db,app
from itsdangerous import URLSafeTimedSerializer
class Users(db.Document):
uid = db.StringField()
username = db.StringField()
password = db.StringField()
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return unicode(self.uid)
def get_auth_token(self):
serializer = URLSafeTimedSerializer(app.secret_key)
return serializer.dumps([self.username,self.password])
Thanks
I changed the user_loader callback to
#loginManager.user_loader
def load_user(userid)
user = Users.query.filter(Users.uid == userid).first()
return user
and this solves the issue I am facing and it is generation a cookie called 'REMEMBER_ME' in my browser. But still I am finding a way to called the token_loader callback and when it would be called.