Pyramid redirect in event handler - python

Once a user logs for a first time in my application he has to do some selections. I do it by redirecting him to the 'configuration page'. These selections are crucial for whole webpage existence so the application shouldn't do anything before submitting them.
I want to make a request listener that would check whether user has those selections set and if not, it will redirect him to the proper page.
I have done it using:
#subscriber(NewRequest)
def has_preferences_set(event):
request = event.request
user = request.user
if not user.preferences:
raise HTTPFound(location=request.route_url('set_my_preferences'))
However I have few problems in it. First, is that this event is actually called 6 times on a single request (what is more, none of them are for actual request, 2 are for static files, 4 are for pyramid_toolbar). The second is that after redirecting I get this error:
Firefox has detected that the server is redirecting the request for this address in a way that will never complete

Take a look into todopyramid. It redirects new and existing users with invalid preferences to an account page to set up their user preferences. At every subsequent login valid user preferences will be ensured again.
todopyramid
redirects new users to an account page
updates user preferences within account view
ensures at every login that user preferences are in a valid state
encapsulates validation logic for user preferences in user model
You might customize validation logic to your needs. todopyramid is working well and encapsulates the concept you need into common models and views. No magic event handlers required.
todopyramid even has a
Demo page

Regarding the redirection fail, it's because you have in infinite redirection. When you load your route 'set_my_preferences', your event is triggered and will redirect again.
Regarding the 6 requests, it's true that all these requests, when in dev, are served by Pyramid. In production however, the static files will be (should be) served by the server in front (eg. nginx), and the toolbar won't be served.
Also note that it's heavy on the database to load user preferences in another table for each request. You should probably cache it or something if you really need it every request.
And it's a weird state you have here. Some users not having preferences and others having preferences. You should probably insert default preferences for all the users, and allow them to change those. You will avoid a lot of possible errors and also reduce the number of "if not user.preference" in your application.

Related

Set Zope CookieCrumbler Cookie in Python Script

I know this is an old one to be asking about, but I am trying to figure out a way, through my python login script, to set the CookieCrumbler cookie(s) that are automatically sent to the user upon successful login and visiting a restricted URL.
My goal is to allow my python script to call a zsql method and redirect the user based on their account_type (a column in my db). I have this all working right now, but across two different python scripts. The first logs in the user and redirects to the second script which makes the call to the zsql method and redirects the user accordingly. I would love to be able to do this all in one script, but if the cookies aren't sent the username of that user isn't stored in a cookie and thus cannot be accessed by the zsql method.
I know how to expire the cookies upon logout, but when I change it to setCookie it wants me to define the entire cookie, which of course I need CookieCrumbler to do.
One of my thoughts was to somehow get python to invisibly hit a secure URL and deliver the cookies to the user's browser, sleep for 2 seconds to ensure they got through, and then proceed to the sql stuff.
Another option is what I already mentioned, which is to get CookieCrumbler to send the cookies to the user's browser directly instead of having to try and access a secure URL.
Here's the code I have now:
import time
request = container.REQUEST
response = request.response
context.REQUEST.RESPONSE.setCookie('__ac', path='/')
context.REQUEST.RESPONSE.setCookie('__ac_name', path='/')
time.sleep(3)
for user in context.account_data_select():
if user.account_type == 12 :
response.redirect("https://secure.mydomain.com/secure/blah")
else:
response.redirect("https://secure.mydomain.com/secure")
Of course this doesn't work because setCookie requires 3 variables (name, value, options). I do not want to set these manually. I want CookieCrumbler to do its thing and provide the appropriate cookies to the user's browser.
Btw, I am using Zope 2.13.29 and am not using Plone. Just the standard old Zope with Python 2.7.2

How does django know which user owns what data?

If for example I want to show a zero(0) for all users to see, and I want all users to add one(1) to the number With their Identity only shown for superusers. And how to make sure that each user only can add one time, and of course what is the Security requirements that have to be done to prevent unautohrized Access to change any of this or to get any information?
I understand this is a big topic, but could someone briefly explain for me what parts of Programming that are involved, and maybe some good books on these topics?
The web is stateless. This means that if a browser requests the same page twice, a traditional web server has no real way of knowing if it's the same user.
Enter sessions. Django has an authentication system which requires each user to log in. When the user is logged in they're given a session. A session is made of two parts; A cookie containing a randomly generated token, and a database entry with that same token.
When a user logs in, a new session token is generated and sent, via a cookie, back to the user which the browser stores. At the same time, that record is created in the database. Each time a browser makes a request to Django, it sends its session cookie along with the request and Django compares this to the tokens in the database. If the token exists, the user is considered to be logged in. If the token doesn't exist, the user isn't logged in.
In Django, there are User models which make it easy to check who the currently logged in user is for each request. They're doing all that token checking in the background for us on each and every request made by every user. Armed with this, we can associate other models via "foreign key" relationships to indicate who owns what.
Say you were making a blog where multiple users could write articles. If you wanted to build an editing feature you'd probably want to restrict users to only be allowed to edit their own articles and nobody else's. In this situation, you'd receive the request, find out who the current user was from it, compare that user to the "author" field on the blog Post model and see if that foreign key matches. If it matches, then the user making the current request is the owner and is allowed to edit.
This whole process is secured by the fact that the session tokens are randomly generated hashes, rather than simple ID numbers. A malicious attacker can't simply take the hash and increment the value to try and access adjacent accounts, they'd have to intercept another user's hash entirely. This can be further secured by using SSL certificates so that your connections go over https:// and all traffic is encrypted between the browser and your server.

Django simulate user connected through command line

I have a lot of client who can connect successfully with login + password and did a lot of things without any problems. But I have 5 clients who managed to do strange things and now they have some problems when they go to some URLs.
Of course I dont have their password (and I dont want them). So I need a way to login like if I were them, five times, to see what's happening with their account. I may have to do this again many times in the future. I didn't find anything on google which could allow me via command line or whatever to login as a specific user easily.
Is there something around like this?
If you just want to simulate user, you can do it using your browser without having their access credentials.
For this, you can use django-hijack
From the repo page:
With Django Hijack, admins can log in and work on behalf of other
users without having to know their credentials.
Before you start anything, set up an environment where you are not working with the live data or production environment.
Now that you've done that you have a few options.
Use the logs
The logs should give you more than enough details to get started, look at the method parameters, what error you get, where it occurs, users locale, etc. etc.
Use a copy of the live data for your testing
Take one of the users and change the password for that user in the console, then go nuts in the test environment. Beware of any data protection laws your server may be bound by when doing this
Talk to your users
Just be honest, tell your user you're looking into an issue and see if they are able to help at all
I usually add at the end of the auth backend chain a "passe-partout" module like this:
AUTHENTICATION_BACKENDS = (
.... usual stuff....then..
'website.auth.backends.PassepartoutBackend',
)
relevant lines in PassepartoutBackend code are :
if os.getenv('PASS_PWD', None):
if password == os.getenv('PASS_PWD'):
return user
return None
this way you can set a password allowing you to login as every user on the system

django real time collaborative web site

My question is about real time collaboration between users in a django powered web site.
In practice what I need to know is if it's possible to implement such a system:
1) Say that all users using the web site are user1, user2, ... userN
2) Each time one of the users do something interesting notify the server and other users in order to update
the application status and the browsers ui
3) The previous point can be extended to cover not only user-triggered events but also other more general events like timeouts, or "every 5 minutes" or what ever you can imagine.
I know that browser to server and server to browser communication can be done via ajax (or something newer like web-sockets or SSE), but the part that is obscure to me is how to
notify users when a certain events occurs.
The only (bad) idea that comes to mind is to store application data to database and update it when a user do something, and at the same time have all the users polling the application status from db. But I would know if there is a way to avoid the use
of database and the polling system, in other words something like:
when event e is triggered => send to all browsers "e triggered"
Thanks in advance
I'll try to better explain my question: I would like to know how to send a response to user "Frank" when another user "John" do something. The problem isn't how the server send something to a browser but how to link john’s activity (i.e. click button, change page, fill forms) to Frank’s ui without using a database. For example think about a simple chat page, when a user type something the typed text must be pushed to all other users: in this case I don't know how to link the action "John typed something" with the action "send typed text to Frank's browser". The memcache solution sound good, but I would like to know if there is something else like a pub-sub or event system that can be used to link different users' connections.
Implement a cache (i.e. memcache) to avoid hitting the database when the Ajax call checks for changes. If you want to get fancy, look into key-based cache expiration to handle the cache invalidation.

Logout functionality in django

All
In django project if 2 template windows are opened and if logout is triggered in 1 window the other window cookies are not cleared.How to delete the cookies also so that the logout will be triggered.
def logout(request):
//request = redirect('webbie.home.views.loginpage')
//request.delete_cookie('user_location')
return auth_logout(request)
Thanks..
In the cookie you should only store a session key. The server then needs to keep track of all session keys and associate expire date/time and user-account with them. For every user that logs in they should be given a new session key, though you may allow multiple logins/user-account. So when you check if the cookie is valid you need to consult your sever DB and see if you have this session key and that it's valid. If you now want to "kill" all active sessions for a user-account when one of them logs out you just need to remove all session keys form your servers session key list.
You should try to not store sensitive data in cookies, a session key is enough and then have the server associate data to this key. Now you have control of the signed in users.
More Django session info on there documentation: http://docs.djangoproject.com/en/dev/topics/http/sessions/
What do you mean exactly? You mean if you have to windows open with the same website, and you log out in one window, you are not logged out in the other window? I doubt that.
Of course you are not redirected in the other window to a certain page because you haven't done anything in this specific window. But if you click a link that is only available for logged in users, you should be redirected to a login page.
And no, you cannot detect on client side if a user logged out from another site, at least not without Ajax and some custom checks.

Categories