How to trigger an action on session timeout in Django - django

I wonder how I could trigger an action whenever a session timeout occurs. Is there a way to set up a callback function that would be executed before the session data get destroyed? I need a solution that also works for unauthenticated users.

Assuming that you are using the default session database backend, you can use a Django signal to detect when a session is deleted from the DB, following an approach similar to this:
Django - detect session start and end
Note that in Django 1.5+ the command to use is clearsessions, and not cleanup.
For more details you can refer to the official documentation on clearing the session store.
If the cronjob configuration is not feasible in your case, you can also clear the session store in one of your views, by doing something like this:
from django.core import management
management.call_command('clearsessions')

Related

Django multitenant using middleware - can you persist connections

I'm using django with django-tenants for a SaaS app and it is using the user's subdomain to set the db schema in postgresql. So a call to user1.app.com will use the 'user1' schema.
Each call to a view creates a new database connection by default. If the view call ajax, a new connect/disconnect happens. Using this method works as each call gets it's postgresql search path set to the correct schema using the django-tenants middleware.
My question is if I set CONN_MAX_AGE to persist connections for a period of time to reduce the heavy connect/disconnect load on the server, will django pool connections from multiple users potentially using different schemas? I am concerned, because:
All users are using the 'default' DATABASE. (just the search path changes)
I don't see any logic that binds a connection to a unique user session.
The built in development server ignores the CONN_MAX_AGE setting so I can't test locally.
I have looked into the connection_created signal, but I would be duplicating logic with django-tenants and I'm not sure of any unintended consequences.
Using django 4.0.7 and posgresql 12.

django_auth_ldap vs postgres db using django models

I am creating an app where I store the USERS in a Postgres database with the help of the standard User Model, in my Django app i use Django queries to get all needed information, like "first_name", "username" .. etc
I implemented Django_auth_ldap to start storing user identification data in an Openldap server if i want. But now, i'm confused to how to get the data i used to get using django queries. i don't want to change the behavior in my views, i want to continue using Django queries
This looks like it describes some of what you want: https://django-auth-ldap.readthedocs.io/en/latest/users.html
You can perform arbitrary population of your user models by adding listeners to the Django signal: django_auth_ldap.backend.populate_user. This signal is sent after the user object has been constructed (but not necessarily saved) and any configured attribute mapping has been applied (see below). You can use this to propagate information from the LDAP directory to the user object any way you like. If you need the user object to exist in the database at this point, you can save it in your signal handler or override get_or_build_user(). In either case, the user instance will be saved automatically after the signal handlers are run.

Flask Login Sessions Not Working

I'm having an issue with Flask-Login where for some reason it seems to clear the data from my session. This issue only seem to happen to me when I run my application on AWS within a Docker container. There doesn't seem to be any issues when this is run locally within a Docker container. The container kick starts the application using supervisord to launch the nginx and gunicorn servers.
I'm using Flask-Login and SQLAlchemy to handle my user logins. I'm creating a custom token using the get_auth_token() method in my User model which stores the token with some session data in my database. I use the token_loader and user_loader callbacks to retrieve my User data from the database which works fine.
However, if I'm not actively using my application for a few minutes the session data seems to disappear when I change to a page that requires a login. My session cookie remains unchanged and my token_loader or user_loader callbacks never seem to be called. To work out what might be happening with the session I attached a #app.before_request handler to print the session contents:
[2015-09-29 14:47:21,348] DEBUG in __init__: <SecureCookieSession {u'csrf_token': '51b5b253c55ac954c1bc61dd2dca513e18c4d790', u'_fresh': True, u'user_id': 3, u'_id': 'd3adbd2ed3905986d515aeb04cd1ff7d'}>
[2015-09-29 14:47:21,382] DEBUG in __init__: <SecureCookieSession {u'_flashes': [('message', u'Please log in to access this page.')]}>
It appeared that all of the user information was there for me to be able to load my user but it has bailed out and re-directed to the login page with the Flask-Login flash error. This re-directs before it even touches my callbacks to load the user from the database.
Is this possibly just a set up issue with my server configs that is causing an issue with domains? I'm not really sure what I need to look at and try to debug this further.
This is a known bug in Flask-Login that was fixed around release 0.2.10 (by me). The bug reappeared in release 0.3.0 of Flask-Login, which as of today is the most current release. I submitted a new fix, plus a unit test to prevent this from ever happening again. The fix was merged a few days ago, but a 0.3.1 release has not been made yet.
Bug report: https://github.com/maxcountryman/flask-login/issues/231
My pull request with the fix: https://github.com/maxcountryman/flask-login/pull/237

How do I clear a flask session?

While importing flask, we import modules such as session etc.
SecureCookieSession is a kind of dictionary, that can be accessed using session.
Now, I try to clear all the junk variables that I used while trying to build a website.
One of the answers on stackoverflow used a command like session.clear() for clearing the contents of a session. But such a command gives an error that no such command exists.
Can anyone point out for me how to clear the SecureCookieSession and how to clear the session every time I shutdown the server or close the website?
from flask import session
session.clear()
I use session like this with flask, it does work.
I don't use SecureCookieSession though, but maybe it can help.
You can also iterate through the session and call session.pop() for each key in your session. Pop will remove the variable from the session and you don't have to keep updating your secret key.
for key in list(session.keys()):
session.pop(key)
As pointed out in Jerry Unkhaptay's answer, as well as in corresponding Flask documentation section, you can simply do:
from flask import session
session.clear()
Though, as, fairly, pointed out in comment, by alejandro:
If you are also using flashed messages in your application, you should consider that flashed messages are stored in the session and can, therefore, be erased before they are flashed if you clear the session.
My suggestion is to take advantage of list comprehension:
[session.pop(key) for key in list(session.keys())]
it is essentially the same for loop as in TheF1rstPancake's answer, though a one-liner. We can remove everything, except flashed messages, from session (or add add any other conditions, for that matter) quite easily, like so:
[session.pop(key) for key in list(session.keys()) if key != '_flashes']
As an additional option, if you're using the flask_login package, all you have to do is call logout_user in the context of a request.
The logout_user function pops the session key as mentioned in other answers, while also cleaning up the remember cookie and forcing a reload of the user in the login_manager. It also sends a logged-out signal (if signal handling is important in your app).
from flask_login import logout_user
logout_user()
If you want to pop and put it to g, you can try:
from flask import g, session
my_value_list = ('sys_info', 'msg')
[setattr(g, s_k, session.pop(s_k)) for s_k in my_value_list if s_k in session.keys()]
There is no way to clear session or anything.
One must simply change the app.config["SECRET_KEY"] and the contents in session dictionary will get erased.

How do I set session variables at login using django-registration and auth?

I'm using django-registration to log users into my application. That part works fine. The part that I cannot figure out is how to set custom session variables when the user logs in. For instance, I'd like to populate variables containing UserProfile data as well as the output of a few other functions. Then I'd be able to use that information in subsequent views/templates.
If anybody can point me to a tutorial online or post some sample code, that would be great.
I'm using django 1.1 and Python 2.6
If you don't want persistent storage of user data (just additional session data) have a look at:
http://docs.djangoproject.com/en/dev/topics/http/sessions/
The sessions framework will most probably be already enabled if you use django.contrib.auth.
If you want persistent storage of additional user data (not only in a session, but in the database), you will store them in another "profile" model:
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
I realize #stefanw provided you an alternative solution, but to answer the original question:
Setting session data at login is difficult because the easiest place to set that data is in your view function, and the particular view function you'd want to modify is a part of the contrib.django.auth app.
So your options would be the following:
Create a small middleware class to set your session data.
Create a template tag or other bit of code than can be integrated into the login template or subsequent page that will set the data you want.
Write your own custom login view function (it's really quite easy, actually).
Happy django-ing!