Logout user when they leave site - django

I want to be able to automatically log users out when they leave my Django site. Not just when they close the browser, but whenever they navigate away to a different site. Is this possible?
I'm displaying sensitive data to the user, and if they were to go to a new URL, and then hit the back button, I don't want the sensitive data displayed. I want them to be forced to log back in.
Is this possible? Or is this something I would have to do on the front end?

Check out this answer on how to detect when a visitor moves away from the page.
Documentation: Page Visibility API
Logout user via Ajax:
from django.views.generic import View
from django.http import JsonResponse
from django.contrib.auth import logout
class LogoutView(View):
"""
The logout view class. This will log the user out and invalidate the session.
"""
def post(self, *args, **kwargs):
logout(self.request)
return JsonResponse({'success': True}, **kwargs)
If you only want to 'logout' user if they leave the page, try hooking into onbeforeunload event.
$(window).unload(function () {
/* login for ajax call goes here */
});
WindowEventHandlers.onbeforeunload

Related

Django Redirect after Successful Login

I have a requirement that whenever I login or attempt to request a view that has a login_decorator then the next page be a page where I am required to ask the user to select a business entity (irreespective of the original view requested).
Let's say that the page is http://127.0.0.1:8999/APP/business_unit
To achieve this I configured the following in my settings.py
LOGIN_REDIRECT_URL='/APP/business_unit_selector'
Now when i try to access http://127.0.0.1:8999/APP/range_list
the page goes to http://127.0.0.1:8999/APP/login?next=/APP/range_list I was expecting that the next page after login be /APP/business_unit
but instead, the next page was /APP/range_list
The browser address bar has http://127.0.0.1:8999/APP/login?next=/APP/range_list
Is it possible to achieve what I am trying in Django?
LOGIN_REDIRECT_URL is used unly when next is unspecified. In your test request there is next=/APP/range_list - and that address is used to redirect user after login.
Probably the easiest and most effective solution is to make your own decorator, similar to login_required which redirects to /APP/business_unit_selector&next=<redirect_url> if unit is not selected, and apply it together with login_required. It is not the most efficient solution in terms of redirects number, but is quite clean, and doesn't mess up the login page.
You will also have to handle next parameter in your business_unit_selector view, if you like to achieve natural flow.
Your decorator should be something like
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.utils.http import urlquote
import functools
def business_unit_required(view):
#login_required # probably you want to incorporate it here
#functools.wraps(view)
def wrapped(request, *args, **kwargs):
if not 'selected_business_unit' in request.session:
return redirect('%s?next=%s' % (
reverse('business_unit_selector'),
urlquote(request.get_full_path())))
return view(request, *args, **kwargs)
return wrapped
The reason that http://127.0.0.1:8999/APP/login?next=/APP/range_list is redirecting you to range_list after logging in, is because with next= you are overriding what is specified in your settings file, LOGIN_REDIRECT_URL='/APP/business_unit_selector'.
If I understand correctly you need to user to choose a business entity after logging in.
A couple solutions that come to mind are as follows:
1.) Don't use a separate forms for login and business entity. Instead combine them.
Username
Password
Business Entity
2.) You can also specify in your view if the user doesn't have a buisness entity ResponseRedirect("/APP/business_unit_selector")
docs here

How can I redirect a user to a specific page or run some code logic in a common place after login in Django?

What I want is to redirect the user to a specific page when they log in if a flag is raised. So I know that all of the login requests go through django.contrib.auth.views.login. Do I have to modify this to accomplish what I want to do or is there some other way to do this. So when I log in I hit the index page and that's fine, I can work with that but what if the user tries to access a page where log in is required. Here's what it will look like
login/?next=/page_that_requires_login
so now after login, it will not hit the index page anymore, it will go directly to page_that_requires_login. I am a little new to django but my instinct tells me that I shouldn't have to check this flag on every page. Is there a common place that I can do some code logic after a user is logged in no matter what page they get redirect to?
Django provides decorator called, login_required() which we can attach to any view, where we require the user to be logged in. If a user is not logged in and they try to access a page which calls that view, then the user is redirected to another page which you can set, typically the login page.The following is an example code for a view called restricted.
#login_required
def restricted(request):
return HttpResponse("since you are logged in you can see this page)
Note that to use a decorator, you place it directly above the function signature, and put a # before naming the decorator. Python will execute the decorator before executing the code of your function/method. To use the decorator you will have to import it, so also add the following import:
from django.contrib.auth.decorators import login_required
To set a page to which the user is redirected if he is not logged in, you need to add the something like this to settings.py
LOGIN_URL = "/app_name/login/"
This ensures that the login_required() decorator will redirect any user not logged in to the URL /app_name/login/.
I redirected by groupwise as :
from django.http import HttpResponseRedirect
def loggedin_view(request):
usergroup = None
if request.user.is_authenticated():
usergroup = request.user.groups.values_list('name', flat=True).first()
if usergroup == "staffGroup":
return HttpResponseRedirect("/cmit/userDash")
elif usergroup == "supervisorGroup":
return HttpResponseRedirect("/cmit/supervisorDash")
elif usergroup == "auditGroup":
return HttpResponseRedirect("/cmit/auditDash")
elif usergroup == "mgtGroup":
return HttpResponseRedirect("/cmit/mgtDash")
else:
return HttpResponseRedirect("/admin/")

Diplay error message

I have a site, that has a submit form, but one must be logged in for that. And if the user is not logged in, it redirects it to the login page. And this all fine. My question is, what do I do to display the error message, "You must be logged to submit.", if the user is not logged in and tries to submit the form, but has to display the normal login page if not.
Thank you.
You might want to use decorator #login_required:
from django.contrib.auth.decorators import login_required
#login_required(login_url='/your/login/url')
def your_view(request):
# your view code here
Hope this helps.

Django poll showing after user logs in

When user logs in I would like to check if he has already voted the poll..and if not, redirect him to the poll form page. Tried with user_logged_in signal but it completely ignores my redirect() function.
#receiver(user_logged_in)
def check_poll(sender, user, request, **kwargs):
"""Check if any active polls available and redirect user if needed"""
try:
# there can only be 1 active poll
poll = Poll.objects.get(active=True)
if not poll.has_user_voted(request.user):
return redirect(poll)
except ObjectDoesNotExist:
pass
Maybe I'm doing this the wrong way..Maybe I should modify the request as I am not sure I should return the response here ... Is there any method without modifying the login() view?
The user_logged_in signal doesn't allow you to change the response to the login, it just allows you to take ancillary actions. In order to change the response to the login (which by default is just a redirect to LOGIN_REDIRECT_URL), you do need to use your own login view. Your view, however, can just wrap the built-in login view: call it, and if the response is a redirect and the user hasn't completed the poll, change the "Location" header of the redirect to the poll page before returning it.

How do I redirect users who try to access admin area in Django?

I've noticed an interesting problem with Django's admin area. If I revoke my staff permissions and try to access /admin directly, I would normally expect a redirect to my login page with /admin/ in the query string as a future redirect. However, I get a proper page returned with HTTP code 200 which actually uses my admin/login.html template to render that requested page instead of redirecting. It seems the problem lies within the #staff_member_required decorator, which admin views obviously use.
The question is: is this done on purpose? If not, how can I change this behaviour without too much monkey-patching?
This is done on purpose, because many people implement redirects in thier sites which could block access to the admin panel. Because the admin panel is it's own app it redirects to itself.
# Put this code somewhere it will be imported REALLY early
from django.contrib.admin.views import decorators
def staff_member_required(view_func):
"""
Decorator for views that checks that the user is logged in and is a staff
member, displaying the login page if necessary.
"""
def _checklogin(request, *args, **kwargs):
if request.user.is_active and request.user.is_staff:
# The user is valid. Continue to the admin page.
return view_func(request, *args, **kwargs)
else:
return HTTPResponseRedirect('/my/login/page/')
return wraps(view_func)(_checklogin)
decorators.staff_member_required = staff_member_required #replaces the function in-place