Flask-Login user status monitoring - flask

I'm developing a small website with Flask & Flask-Login. I need an admin view to monitor all user's online status. I added an is-online column in user db collection and try to update it. But I didn't find any callbacks to handle session expires. How to solve it or any better idea?
Thanks!

FYI, Counting Online Users with Redis | Flask (A Python Microframework) - http://flask.pocoo.org/snippets/71/.

You could get away with checking if users last activity time is bigger(older) than session life time.
if that's the case, you will go on an update their is_online status.
the way i have handled the problem in my application was, since i had a last_activity field in db for each user, to log when they have done what they have done, i could check that value vs session life time.

One very crude method is to create a separate stack that pushes and pops when a user logs in. Assuming that session id and userid on your db is not tied together (i.e., you have separate session id and user id), you can maintain a ledger of sorts and push and pop as sessions are created and destroyed.
You will have to put special emphasis on users running multiple sessions on multiple devices...which is why i put a caveat saying this is a rather crude method.

Related

Django Celery - Creating duplicate users due to mutiple workers

I am facing a weird issue with celery in production. Currently, the production server has 4 celery workers which handle all the tasks registered by my django app. No custom queues are defined. The workers are basically 4 separate supervisor conf files.
Now, in my app I am handling facebook webhook data, and I want a user with a specific FacebookID to be only created once on my backend. But, recently I checked and found out that there are users who have the same FacebookID, which should not have happened.
What happened I think was e.g. user with FacebookID 666 sent me a webhook data. Now, a task is created which will create a new user instance in my database with FacebookID 666. Now, before the user is created in my database, the user hits me with another data, which also created a task but under a different worker, and thus I got myself two users with the same FacebookID.
Is there any way I can configure celery to handle a user with a specific FacebookID to create tasks only in ONE worker? Or have I completely misjudged the situation over here?
Essentially, you need a user-level distributed lock to prevent multiple workers from working on the same user. There are several ways to accomplish this, the most straightforward being a database such as mysql or redis. In mysql, the first process would transactionally (1) check for an existing row in a database table with the user ID (e.g., email or other unique identifier) and (2) if no row exists, creating that row; (3) and if a row exists, return early without doing anything. You can also do this in redis using a redlock or for smaller systems just using SETNX

Wait for datastore update before proceeding

I'm working on a lightweight app, and I have quite a few situations where the user submits a form, the form data is processed and pushed to the datastore, and then the user is redirected to a page that displays some of the same data. It's quite often the case that the user gets to the page before the datastore has been updated, so they see old data. Is there any way to have the app wait for the datastore to update before proceeding? The obvious hacky solution is calling sleep(1), but that's obviously not ideal and takes longer than the actual update.
Just get the key the .put() returns:
key = mything.put()
and pass it on to the other page (e.g via urlsafe). The other page can rebuild the key and then
thething = key.get()
will always give you updated data -- i.e, this (key.get()) is one simple way to get strong consistency from the GAE datastore!

How can I push data to a user session?

I need to push changes to my app's session scopes in real time. Each user in session in my app has a similar struct to this:
session.user =
{
name = "Foo",
mojo = "100"
};
Users can modify each others' "mojo." For example, if user Foo received 10 mojo points, and he now has 110, I need to update his session.user.mojo to reflect the additional "mojo" received. I need to modify his session struct, in other words.
Example 2: User in session 1 does something where user in session 2 receives "mojo." The session.user.mojo in session 2 needs to be updated to reflect this change.
Some info:
The inital mojo value is pulled from the database and stored in the session when a user logs in.
"Mojo" updates always take place in the database. "Mojo" stored in the session is used to govern user privileges.
What are my options? Is this even possible? I have absolutely no idea on how to do something like that.
UPDATE I don't want pass the updated values back to the user (the data will refresh when the user navigates between pages). I only want to change them in the appropriate user's session scope.
This answer is ColdFusion 9 specific.
Cache user data (e.g. cachePut()) by user ID, and keep track of their user ID in session. Every update to mojo should retrieve the user data in cache - if present - and update it there as well. Finally, if this is a multi-server environment, setup messaging between the machines that broadcasts the user ID of any change to mojo, servers receiving the message then update their own cached user data.
What this buys you is limiting the amount of database activity that goes on, pretty good liveness, and makes the mojo value available globally, which has the added benefit of being available for purposes other than the user session (e.g. another user can review their profile to see the mojo score).
If you really need to change vars in a particular Session, there's no built-in way to do that. Maybe you can abstract out the logic, instead of accessing the mojo from Session, always access mojo from DB?
update: Why session? How about a big struct in Application scope, and use userID or sessionID as key, and mojo as value? You can also store a timestape like lastUpdated and delete the ones that has not been updated to reclaim your memory. Then from time to time, update your DB? Or... update your DB async if u're worry about performance.

Marking users as new when created via a backend's authenticate in Django

I have an authentication backend based off a legacy database. When someone logs in using that database and there isn't a corresponding User record, I create one. What I'm wondering is if there is some way to alert the Django system to this fact, so that for example I can redirect the brand-new user to a different page.
The only thing I can think of is adding a flag to the users' profile record called something like is_new which is tested once and then set to False as soon as they're redirected.
Basically, I'm wondering if someone else has figured this out so I don't have to reinvent the wheel.
I found the easiest way to accomplish this is to do exactly as you've said. I had a similar requirement on one of my projects. We needed to show a "Don't forget to update your profile" message to any new member until they had visit their profile for the first time. The client wanted it quickly so we added a 'visited_profile' field to the User's profile and defaulted that to False.
We settled on this because it was super fast to implement, didn't require tinkering with the registration process, worked with existing users, and didn't require extra queries every page load (since the user and user profile is retrieved on every page already). Took us all of 10 minutes to add the field, run the South migration and put an if tag into the template.
There's two methods that I know of to determine if an object has been created:
1) When using get_or_create a tuple is returned of the form (obj, created) where created is a boolean indicating obviously enough whether the object was created or not
2) The post_save signal passes a created paramater, also a boolean, also indicating whether the object was created or not.
At the simplest level, you can use either of these two hooks to set a session var, that you can then check and redirect accordingly.
If you can get by with it, you could also directly redirect either after calling get_or_create or in the post_save signal.
You can use a file-based cache to store the users that aren't yet saved to the database. When the user logs in for the second time, you can look in the cache, find the user object, and save it to the database for good.
Here's some info on django caching: http://docs.djangoproject.com/en/dev/topics/cache/?from=olddocs
PS: don't use Memcached because it will delete all information in the situation of a computer crash or shut down.

In django, are all session data deleted if a user logs out?

I need to track some information on users, but would like to retain it for a fixed time period, say a week.
If I set this value via request.sessions, and the user logs out, can I retrieve it if they log back in later? This all assumes that my sessions are normally set to expire in 30 days, if the user neVer logs out.
While thinking about the above problem, I decided to store the data in a table, but I would still like to know the answer to above for referenCe. I also decided not to use cookies due to unreliability.
It would depend on your session backend. But the default backend (backends.db) does delete the row from the sessions table when you log out.
I would recommend adding the data to a field in the user profile. Using the session will give problems even if you don't delete the data. The next time the user logs in you won't know which session id he/she used the last time and normally you only have the session id to look up. Not a user id so you can get all sessions owned by a specific user.