In django an inactive user can't login, but if he is already logged in then he can still use the website until he logs out. Where i can to check why is not work correctly?
If you're worried about this, then you'd need to implement something to check the current user on every request and log them out explicitly if their account is inactive. Middleware would be a good place for this:
from django.contrib.auth import logout
class InactiveUserMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated() and not request.user.is_active:
logout(request)
return redirect(your_login_url)
Place this in MIDDLEWARE_CLASSES directly after the AuthenticationMiddleware, and you should be good to do.
Related
I am working with django rest, I however have an issue in one of my views because, i want to allow both authenticated users and unauthenticated users access the view then check if the user is authenticated then there are some special events to be done by the celery tasks, however, whenever i add the decorator for the authentication_classes, unauthenticated users can no longer visit the page even after setting the permission_classes to allow all
simply my code is here, hope someone can know what i need to add or remove
#api_view(['GET'])
#permission_classes([AllowAny])
#authentication_classes([TokenAuthentication])
def item_details(request, pk):
if request.user.is_authenticated:
#here some tasks
the main issue is that it seams that TokenAuthentication just nullify AllowAny and takes over the checking of the permisssion class
or is there something am doing wrong?
Overriding the authenticate method of TokenAuthentication
myauth.py
from rest_framework.authentication import TokenAuthentication
class TokenAuthenticationSafe(TokenAuthentication):
def authenticate(self, request):
try:
return super().authenticate(request=request)
except:
return None
views.py
from myauth import TokenAuthenticationSafe
#api_view(['GET'])
#permission_classes([AllowAny])
#authentication_classes([TokenAuthenticationSafe])
def item_details(request, pk):
if request.user.is_authenticated:
#here some tasks
I'm trying to log in a user through DRF view.
#list_route(methods=['post'])
def login(self, request, *args, **kwargs):
login_form = LoginForm(request, data=request.data or None)
if login_form.is_valid():
_login(request._request, login_form.get_user())
else:
raise forms.ValidationError("login wrong")
return Response({})
Above code runs without exception, but it doesn't seem to actually log in the user.
When I refresh the browser, the user is still not logged in.
How can I log in the user?
Please don't use DRF to log people in with session.
The warning a few lines after the SessionAuthentication gives you more details about it.
Seems that the _login() method doesn't do what you expect.
As you mention in your your comment. you were using:
from django.contrib.auth.views import login as _login
but this method:
Displays the login form and handles the login action.
You should (as you do) use:
from django.contrib.auth import login as _login
which:
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
I noticed that when I logged in as administrator, I don't need to reauthenticate when I access non-admin area.
However, when I login as simple user and access admin zone, Django, of course, checks whether I am admin.
Where this check occurs? I want to restrict access of moderators to non-admin part of site, so need to check that.
Thank you.
Use the #user_passes_test decorator:
from django.contrib.auth.decorators import user_passes_test
def not_staff_user(user):
return not user.is_staff
#user_passes_test(not_staff_user)
def my_view(request):
...
If you want to restrict ALL pages except /admin/ then middleware is a good option:
from django.conf import settings
from django.shortcuts import redirect
class NonStaffMiddleware(object):
def process_request(self, request):
if request.user.is_staff and not \
(request.path.startswith('/admin/') or
request.path.startswith(settings.LOGIN_URL) or
request.path.startswith(settings.LOGOUT_URL)):
return redirect(settings.LOGIN_URL)
You have the user.is_staff, user.is_superuser and user.is_authenticated functions to check this wether in your views or templates. If you need to do this in your templates, the user is in the {{ request.user }} and also in your views with request.user.
I have some sections on my web site where only logged in users can see their resources.
I also want to make absolutely sure that only that authorized user can modify and delete his/her records. What's the best practice and more secure way of accomplishing this in Django?
Real examples would be truly appreciated.
For my project, I created a Decorator that checked if the right user was logged in:
#decorator.py
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
def same_user_required(func):
def wrapper(request, user):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('login-view'))
if not user == request.user.username:
return HttpResponseRedirect(reverse('login-view'))
return func(request, user)
return wrapper
You then add it to any views that need checking:
#view_profile.py
from apps.utilities.decorators import same_user_required
#same_user_required
def edit_profile(request, user):
Note that my URL contains the username /profile/edit/<username>, which is where the parameter comes from, in the edit_profile view.
Another way is to use the Django built-in decorator, user_passes_test (see Django Book Chap 14 for an example of its usage. You then just have to write the test, not the decorator boilerplate code.
I've added this decorator to one of my views
#permission_required('codename')
When a user visits that page and doesn't have the required permissions, he is redirected the login page, but it doesn't really tell him why he's been redirected there. Worse yet, if he logs in, and still doesn't have the permissions, he's going to be completely clueless as to why he can't access that page!
Isn't there a way I can tap into the messages framework and post an error at the same time?
Not sure what version of Django you are using, but in Django 1.4 and higher you can use:
from django.contrib.auth.decorators import permission_required
#permission_required('app.permission',raise_exception=True)
def myView(request):
#your view code
This will raise a 403 exception and if you have a 403.html page at the base of your template folder it will server this out.
If you are using class based views:
from django.views.generic.base import View
from django.contrib.auth.decorators import permission_required
from django.utils.decorators import method_decorator
class MyView(View):
#method_decorator(permission_required('app.permission',raise_exception=True)
def get(self, request):
#your GET view
Hope this helps.
You can tap into the messages framework and provide an error message. See my answer to an identical question.
You could use login_url parameter in this decorator to redirect to some other page, rather than login page. Or you can simply write your own decorator based on the code from django:
def permission_required(perm, login_url=None):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.
"""
return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
Simply change login_url to some redirect_to and it won't cause any confusion.
Use #permission_required_or_403('codename')
This will redirect the users to a 403 'permission denied' error page.