KeyError: 'user_available' - flask

I am trying to implement a check that if a user is available then render a specific template. I am using this condition if session['user_available']: where session is imported from flask. But I am getting KeyError: 'user_available' error. If this method is deprecated then what is the updated code for assessing the availability of current user using session.

At the time of the request, the key-value pair does not exist in the session. This results in the KeyError.
Much of this session is to be used like a dict. So you can query if a key-value pair exists within the session. This should assume that even if the key is not part of the session, no KeyError is thrown.
if 'user_available' in session and session['user_available']:
# The key is present in the session and the value is set.

Related

In Django, what would be the proper way to persist session information?

I am designing a REST app in django, which I intend people to use without a browser (just direct API calls with curl or whatnot). I have several different views where I want to pull in information about the session based on values that may have been a acquired from previous calls to other views. It seems that every time a view is called the "request" object passed in is an entirely new session, so I'm wondering how I can persist values the "correct" way?
Example code:
def login(request):
...
##I want to assign a token value to this session that is persisted to the entity requesting it
request.session['token'] = response.json()['auth']
...
def grabSomeValues(request):
...
##I want to grab the session token value in here but of course the request object in the case is a completely new one that does not have that token value it seems
print(request.session['token']
....
I think Middleware would help you.
The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis.
https://docs.djangoproject.com/en/2.2/topics/http/sessions/

Using Django Session Framework with a Token instead of a Cookie?

I have a DRF API with protected endpoints that returns filtered data depending on what a user has permission to access.
I have a separate Django OAuth2 provider which contains the user models and the values necessary to determine what the user has permission to access.
The user should be able to authenticate via a login endpoint on the DRF API. The API in turn gets a token from the Oauth2 provider on behalf of the user, and makes a few calls to get a list of resources the user is allowed to access.
Ideally the DRF API would then generate a token and return it to the user. Whenever the user makes a subsequent request (after login) using the token, the API would be able to filter results via the values returned by calls to the Oauth provider.
The question is how to store this information. This feels similar to storing data in an anonymous user session, but using a request header instead of a cookie. I've considered rolling a customized version of django.contrib.sessions.middleware.SessionMiddleware, but I'd prefer to use an established method instead of writing custom code, as this seems like it should not be a unique problem.
To reiterate: Is it possible to create an anonymous user session, store information it it, and retrieve the session via a request header instead of a cookie?
Here is the original SessionMiddleware.process_request provided by Django. Lets take a quick look at it.
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
request.session = self.SessionStore(session_key)
We can clearly see that it explicitly gets the session identifier form the cookies using the SESSION_COOKIE_NAME property defined in the settings. Hence, we absolutely must create our own subclass of this SessionMiddleware and define our own process_request behaviour.
Irrespective of whether the incoming token is authenticated or not, we need to retrieve the token value from the header, and use that to initiate our session engine. Here's how it might look:
from django.contrib.sessions.middleware import SessionMiddleware
from django.conf import settings
class CustomSessionMiddleware(SessionMiddleware):
def process_request(self, request):
session_key = request.META.get("HTTP_%s" % settings.SESSION_KEY_NAME, None)
request.session = self.SessionStore(session_key)
Make sure you set the SESSION_KEY_NAME property in your django settings file to the name of the header key in which this token will be sent. Then, replace django's original SessionMiddleware with the path to your custom session middleware and your requests.session should start giving you data based on the input token.
Note: You may also need to modify the process_response behaviour since you may not need to send back Set-Cookie headers.

Set session key

How can I change the session key used by a django session? I'd like to support multiple simultaneous sessions in the same browser by specifying an ID in the URL and then incorporating that ID in the session key.
I've tried simply:
request.session.session_key += key
But I get an AttributeError saying that I "can't set attribute".
You could achieve this by writing your own SessionMiddleware (based of Django's django.contrib.sessions.middleware.SessionMiddleware) which supports looking up and storing multiple seperate sessions linked to the same user.
Have a look at the source of the SessionMiddlware, it seems that it quite simply gets a cookie by the name of 'sessionid' (by default), creates a enging.SessionStore instance and stores it as a 'session' attribute of the request instance.
You could theoretically do the same only getting/setting your own cookie names (i.e postfixed with the identifier passed in the request params), and store it in your own attribute (i.e request.custom_sessions) and then be able to use it wherever a request instance is available.

How Can I retain session information once a user registers (Django)?

When a new user is created, I want to retain some of the information in their session
e.g. things a user has stored in their session I want to use once they have registered (or logged in).
I would use either a post_save signal on the user model (or an auth login signal), but it appears that the signals don't put the request, or session into the signal sent. It also seems I can't easily get the session from just the user.
I'm using Django 1.4
Edit: let me give an example.
The problem boils down to this - I may want to retain information for a user's activities before they login, but where do I store this information before they login? A good place would be a session (or I could link the data held in a db to the session, using the session a little like a makeshift user).
In any case, until they login, I can simply use their session like a user credential, and store information that persists so long as their cookie does (how else can could I reliably track an anonymous user?).
But once they register (or log-in), I want to move that information from the session, into the account properly. One good reason is that it would make sense to delete data from anonymous users periodically, whereas registered user's data would be persisted.
To do this I simply want access to the session (could be via the request) from a handler to the new-user signal, so I can make a one-off transfer from data in the session. But the new-user signal doesn't hold the session (or request).
If you're using django.contrib.sessions and django.contrib.auth for the job, the session data should be retained automatically after login.
Moreover, the user_logged_in signal is sent along with request actually.
Edit:
So use user_logged_in signal. It carries request. Pick some specific key to store unauthenticated user's data (e.g. "_anonymous_data"). If that key is set on request.session while handeling signal, simply rewrite data on request.user.get_profile() object, call save and del request.session["_anonymous_data"].
The code to retreive it could look something like:
if request.user.is_authenticated():
user_data = request.user.get_profile()
else:
user_data = requerst.session["_anonymous_data"]
It's only a scratch of course. You don't want to hardcode session keys or write such logic in views. If you need it application wide, embed it in some abstraction class which takes request in __init__.
you could try using sessions:
https://docs.djangoproject.com/en/dev/topics/http/sessions/?from=olddocs

Editing session of another user in Django

How can I do this
request.session['key'] = 'value'
for the user which user_id is 47?
Keep in mind that I'm not currently logged in with that user, I want to do it in shell.
See the section of the Session docs entitled "Using sessions out of views".
The problem though is that Django doesn't store the user with the session (by design, for security purposes). So the only way to retrieve a session is through it's key. That key is stored with the user's client and passed to the server to associate the session with the logged in user. In other words, you're going to have a hard time determining which session belongs to which user.
More to the point, the session data is actually encrypted in the database as well, so there's not even any way to query directly for the user id stored in it. The following will work, but you'll have to query each session one by one to get the right user. Depending on how many sessions your database currently has, this could be extremely expensive. Mark as USE AT YOUR OWN RISK
from django.contrib.sessions.models import Session
from django.contrib.sessions.backends.db import SessionStore
for session in Session.objects.all():
data = SessionStore().decode(session.session_data)
if data.get('_auth_user_id') == user_id_you_want:
user_session = SessionStore(session_key=session.session_key)
# you can modify the session data here like normal, then:
user_session.save()
The answer depends entirely on the session storage/engine you're using.
So, the generic answer would be: Wherever the session is being stored, modify it there.
For the database backend: UPDATE django_session SET session_data=[whatever] WHERE session_key=[whatever];
You'll also need the session key and the AES key stored in the client browser.
Alternatively, send them to a controller that updates the session.