I am working on a django project and I am using the default auth app for authentication.
I know that there is a last_login
field in user model which stores the user's last login time.
When a staff user logs in first time into the admin panel, I want to check if last_login
field is none & redirect him to the change password page.
Where should I put this check?
I have tried to use a custom login form and override the default confirm_login_allowed
method on it, but it seems like I can only raise a validation error to block login attempt using these.
I also tried using django.contrib.auth.signals.user_logged_in
Signal but that also does not allow me to return a redirect response when last_login
is None
.
I want to know how I can return a redirect response after the user has been authenticated.
First make sure you have SessionMiddleware and AuthenticationMiddleware middlewares added to your MIDDLEWARE_CLASSES setting. request. user will give you a User object representing the currently logged-in user.
from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) # Redirect to a success page. ... else: # Return an 'invalid ...
staff. - A user marked as staff can access the Django admin. But permissions to create, read, update and delete data in the Django admin must be given explicitly to a user. By default, a superuser is marked as staff.
Customise Django admin using AdminSite
and use login_form attribute to give the custom login form for the Admin login page.
admin.py
class MyAdminSite(AdminSite):
login_form = CustomAdminLoginForm
admin_site = MyAdminSite(name='myadmin')
admin_site.register(User)
admin_site.register(Group
urls.py
When overriding the Admin we have to get rid of Django default admin
from app.admin import admin_site
url(r'^admin/', admin_site.urls)
forms.py
AuthenticationForm have the confirm_login_allowed
method use this to grant permission to login in or not login in.
class CustomAdminLoginForm(AuthenticationForm):
def confirm_login_allowed(self, user):
if user.last_login:
raise ValidationError(mark_safe('Hey first time user please reset your password here... <a href="/test">test</a>'), code='inactive')
Note: There is lot of edge cases you have to consider for this approach.
date_joined
comes rescue. last_login == date_joined
Edit:
You can use signal to check the logged in user and apply the config_login_allowed
logic here...?
from django.contrib.auth.signals import user_logged_in
def change_password_first_time(sender, user, request, **kwargs):
# Your business logic here...
user_logged_in.connect(change_password_first_time)
Django admin is not that configurable. You should hook into its internal views. Login/logout views are inside Django AdminSite
class (the one you usually access by admin.site
). My implementation is a bit hacky but small:
Paste at the top of urls.py
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
class MyAdminSite(AdminSite):
def login(self, request, extra_context=None):
new_user = False
user = None
username = request.POST.get('username') # Hack to find user before its last_login set to now.
if username:
user = User.objects.filter(username=username).first()
if user:
new_user = user.last_login is None
r = super(MyAdminSite, self).login(request, extra_context)
if new_user and request.user == user and isinstance(r, HttpResponseRedirect): # Successful logins will result in a redirect.
return HttpResponseRedirect(reverse('admin:password_change'))
return r
admin.site = MyAdminSite()
If you want a cleaner solution I suggest to use a boolean inside user model instead of relying on last_login
so you could just check request.user
instead of my hack into request.POST
.
You could read AdminSite.login
and django.contrib.auth.views.login
to see what is actually happening inside Django.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With