I have created a list of 5 users. How do I find out which user has logged in currently? Also please mention, if there is any way to find out if the super-user has logged in?
My requirement is, I want to restrict the access of certain pages in the templates only to the superuser.
Current user is in request object:
def my_view(request):
current_user = request.user
It's django.contrib.auth.models.User class and it has some fields, e.g.
is_staff - Boolean. Designates whether this user can access the admin site;
is_superuser - Boolean. Designates that this user has all permissions without explicitly assigning them.
http://docs.djangoproject.com/en/1.1/topics/auth/#django.contrib.auth.models.User
So to test whether current user is superuser you can:
if user.is_active and user.is_superuser:
...
You can use it in template or pass this to template as variable via context.
Sounds like you should be using the built-in permissions system for this.
Check out the user_passes_test decorator for your views. Django snippets has a related decorator:
These decorators are based on
user_passes_test and
permission_required, but when a user
is logged in and fails the test, it
will render a 403 error instead of
redirecting to login - only anonymous
users will be asked to login.
http://www.djangosnippets.org/snippets/254/
Related
I want to have authority control over my project. Some users can see some app's entries while others can't. I want to set permissions on apps instead of models, I have searched, but only found how to set permissions on models. So, I want to know how to set permissions on apps.
You can make decorators to selectively allow users to access the page
Make this decorator
def filter_users(func):
def checker(request,*args,**kwargs):
if some_condition: #This condition will tell you whether to allow this perticular user
return func(request,*args,**kwargs)
else:
return render('invalid.html') #return a page telling the user that he is not allowed
return checker
Now just apply this decorator to all the views that you want to prevent 'some' users from accessing.
Ex:
#filter_users
def some_view(request):
#Do Something...
Now only allowed users will be able to see the view, rest all will get the invalid page
You can apply this decorator to all the views of the perticular app that you want to restrict access to
I am working on an app where the user will be able to login to his profile. I am using Django-registration-redux. I am using the below code to inculde in my project.
LOGIN_REDIRECT_URL = '/profile/view/(?P<pk>[0-9]+)/'
I want to redirect the user to his profile after logging in. I know that is not the way you can actually call an url in settings file. any solution for the problem?
I believe you can use https://docs.djangoproject.com/en/dev/ref/urlresolvers/#reverse-lazy to add URL resolution to a setting.
You don't need to pass the user pk to the view. You can get this value and every other data field of the user from request.user object.
As stated in Django docs, you could do something like this:
def profile(request):
if request.user.is_authenticated:
# Do something for logged-in users.
request.user.do_something()
[...]
else:
# Do something for anonymous users like redirect to registration
pass
I would like to create a Mixin which will:
First - Check if a user is authenticated, if not, redirect to login url. If yes...
Second - Check if user has a defined Profile (a user), if not, redirect to Profile creation, else, allow user to access the View.
I was planning to do sometinhg like:
class ProfileRequiredMixin(LoginRequiredMixin,PermissionRequiredMixin):
#TODO check how multiple inheritance works treating conflicting methods
'''This Mixin should first check if user is autheticated, if not,
redirect to login. If it is, check if it has a profile.
If it does not, redirect to profile creation url. If it has, allow
access to view.'''
pass
But I am confused as how to overwrite the handle_no_permission() and dispatch() methods.
I solved the problem in the following way:
class TestIfHasProfileMixin(UserPassesTestMixin):
'''This Mixin should first check if user has a profile.
If it does not, redirect to profile creation url. If it has, allow
access to view.'''
def test_func(self):
try:
Profile.objects.get(user=self.request.user)
return True
except Profile.DoesNotExist:
return False
def handle_no_permission(self):
'''to:[login,Profile] will signup or create profiles'''
if self.raise_exception:
raise PermissionDenied(self.get_permission_denied_message())
return redirect('users:create-profile')
class ProfileRequiredMixin(LoginRequiredMixin,TestIfHasProfileMixin):
'''This Mixin should first check if user is autheticated, if not,
redirect to login. If it is, check if it has a profile.
If it does not, redirect to profile creation url. If it has, allow
access to view.'''
pass
Now every view that requires a Profile inherits from ProfileRequiredMixin, which will first test for login (redirect to login creation if there is not) and after that check for Profile and redirect to Profile creation if none exists.
I am using django and have email verification feature so when someone verifiy email , I activate his/her account by setting status. If some one will someone else email address then he will not be able to verify and will not able to login with that. So I was expecting django to look at status of user also while login as this status field is in table that is of django auth app. While on login django tries to login with only username param. So on login it says:
MultipleObjectsReturned at /accounts/login/
get() returned more than one User -- it returned 2! Lookup parameters were {'username': u'kaasib122#gmail.com'}
Is there a way to add status field also in lookup? Is there something in cofiguration for that or I need to write some sort of login backend for that? Or should I write my own view for login table in some different way? What is recommended way? Also I am thinking to let user either login using email or username in username field. So what is recommended way?
You need to write an authentication backend that suits your needs. Check out the django documentation.
Basically, you will need to write an "authenticate" method which will use "status" in the filter parameters. For using email or username, you could basically filter on one field (username or email) and if no User objects are returned for that field, filter on the other. Or you can get the user in a single filter by ORing those fields. Here's a pseudocode:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class AuthenticationBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email=username, status=True)
except User.DoesNotExist:
try:
user = User.objects.get(username=username, status=True)
except User.DoesNotExist:
return None
# check password too
if user.check_password(password):
return user
return None
Note that when you write new authentication backend, you need to add it to AUTHENTICATION_BACKENDS parameter in your settings.py for it to be used. If you don't need the default one Django provides because you have customized it, just override that parameter, no need to add to the tuple.
i've recently implemented a simple change password view in my django project. The thing is that the old session should be destroyed for security reasons. What's the best way of doing this without asking the user to log in again.
I think i could just logout/login him/her, something like this:
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
#login_required
def change_password(request):
# My stuff
request.user.set_password(new_password)
request.user.save()
# I need this:
logout(request)
login(request,request.user)
But i think this is not the best idea. What do you think?
Is there another way to do this?
Am I missing something? (I mean, is this secure)
Take a look at this app https://github.com/atugushev/django-password-session.
This package makes invalidated all sessions (except a current session) after change a password.
Also this feature finally was implemented in Django 1.7. See: https://docs.djangoproject.com/en/dev/topics/auth/default/#session-invalidation-on-password-change
I just found out that this is now a built-in feature of Django, and has been since 1.7:
https://docs.djangoproject.com/en/1.7/topics/auth/default/#session-invalidation-on-password-change
Essentially, all sessions now include a hash of the users' password, so if the user ever changes their password, all their existing sessions are automatically invalidated.
So, the short answer to your question is: upgrade django.
One possibly undesirable side effect of this change is that, by default, a user ends up having to log in again as soon as they change their password. So you probably actually want the current user session to stay logged in. See the docs already linked, Django's built-in views for password change do that for you default, or you can manually call a function called update_session_auth_hash
django clears the session on logout so you will be fine:
https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.logout
When you call logout(), the session data for the current request is completely cleaned out. All existing data is removed. This is to prevent another person from using the same Web browser to log in and have access to the previous user's session data.
I don't understand whats are these security reasons that forces to reset session. But, the way is:
#login_required
def change_password(request):
request.user.set_password(new_password)
request.user.save()
username = request.user.username
logout(request)
user = authenticate(username=username, password=new_password) #<-- here!!
if user is not None:
login(request,user)
else:
#raise your exception
you should authenticate before login. Quoting doc:
Calling authenticate() first When you're manually logging a user in,
you must call authenticate() before you call login(). authenticate()
sets an attribute on the User noting which authentication backend
successfully authenticated that user (see the backends documentation
for details), and this information is needed later during the login
process.