I'm learning how to implement user login in GAE following the instruction in http://gosurob.com/post/20024043690/gaewebapp2accounts.
Below is a portion of the code that creates a user aware handler that my other handlers are supposed to inherit. This allows me to simply return user info by self.user. Now my question is how do I retrieve the user info in a ndb class which obviously inherits ndb.Model rather than BaseHandler. Please advise. Thanks!
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
#super(BaseHandler,self).dispatch()
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def auth(self):
return auth.get_auth(request=self.request)
#webapp2.cached_property
def user(self):
user = self.auth.get_user_by_session()
return user
#webapp2.cached_property
def user_model(self):
user_model, timestamp = self.auth.store.user_model.get_by_auth_token(
self.user['user_id'],
self.user['token']) if self.user else (None, None)
return user_model
class Global_Var(ndb.Model): #<<< This is the ndb class from which I want to use the user info.
current_user = ndb.StringProperty()
#staticmethod
def get_id():
return user['email'] #<<< This, of course, errors out since user is not defined in this class
Related
I'm using Apache mod_wsgi to serve django. I'v also use Django-cuser middleware that makes user information always available. And i can't really understand how this middleware works. The specific source code:
class CuserMiddleware(object):
#classmethod
def get_user(cls, default=None):
"""
Retrieve user info
"""
return cls.__users.get(threading.current_thread(), default)
#classmethod
def set_user(cls, user):
"""
Store user info
"""
if isinstance(user, str):
user = User.objects.get(username=user)
cls.__users[threading.current_thread()] = user
Why use threading.current_thread() as a key for user? As i underastand Apache does not create different theads for requests.
I'm having trouble creating admin pages on my Python Google App Engine site. I think the answer should be pretty straightforward, but honestly, I've been trying to understand how classes inheriting from other classes, or using functions to wrap other functions, and I just can't seem to get a good understanding of it.
Basically, my site has two kinds of pages: the main page, and then some pages that allow the user to perform admin actions. The main page can be seen by anyone without signing in. The other pages are for admins. The only users with accounts are admins, so I've set up webapp2 sessions, and as long as
self.sessions.get('username')
returns something that's enough to be allowed access to the other pages.
Here are my handlers:
class BaseHandler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render(self, template, **kw):
self.response.out.write(render_str(template, **kw))
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
# Returns a session using the default cookie key.
return self.session_store.get_session()
class MainHandler(BaseHandler):
def get(self):
animals = Animal.query().fetch(100)
self.render('index.html',animals=animals)
class AdminHandler(BaseHandler):
def get(self):
if self.session.get('username'):
self.render('admin.html')
else:
self.render('signin.html')
class ReorderHandler(BaseHandler):
def get(self):
self.render('reorder.html')
def post(self):
#Change order of item display
self.write('OK')
class DeleteHandler(BaseHandler):
def get(self):
self.render('delete.html')
def post(self):
#Delete entry from db
self.write('OK')
class AddHandler(BaseHandler):
def get(self):
self.render('add.html')
def post(self):
#add entry to db
self.write('OK')
class SigninHandler(BaseHandler):
def post(self):
#Check username and password
if valid:
self.session['username'] = username
self.redirect('/admin')
else:
self.write('Not valid')
The AdminHandler lays out the basic logic of what these Admin pages should do.
If someone is trying to access an admin pages, the handler should checks to see if user is signed in, and if so, allow access to the page. If not, it renders the sign-in page.
Reorder, Delete, and Add are all actions I want admins to be able to do, but there might be more in the future. I could add the AdminHandler logic to all the GETs and POSTs of those other handlers, but that is extremely repetitive and therefore I am sure that it is the wrong thing to do.
Looking for some guidance on how to get the logic of AdminHandler incorporated into all of the other Handlers that cover "administrative" tasks.
Update: Brent Washburne pointed me in the right direction enough to get the thing working, although I still don't feel like I understand what the decorator function actually does. Anyway, the code seems to be working, and now looks like this:
def require_user(old_func):
def new_function(self):
if not self.session.get('username'):
self.redirect('/signin')
old_func(self)
return new_function
class AdminHandler(BaseHandler):
#require_user
def get(self):
self.render('admin.html')
class AddHandler(BaseHandler):
#require_user
def get(self):
self.render('add.html')
#require_user
def post(self):
name = self.request.get('name')
qry = Animal.query(Animal.name == name).get()
if not qry:
new_animal = Animal(name=name)
new_animal.put()
self.write('OK')
And so on for all the other "admin" Handlers.
Here's a brute-force way to ensure a user is logged in for every page (except the login page), or it redirects them to the login page:
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
if not self.session['username'] and self.request.get('path') != '/login':
return redirect('/login')
A better way is to add this code to the top of every get() and put() routine:
def get(self):
if not self.session['username']:
return redirect('/login')
An even better way is to turn that code into a decorator so all you need to add is one line:
#require_login
def get(self):
....
I have this initialize function which sets self.user if user has logged
class MainHandler(webapp2.RequestHandler):
def initialize(self, *a, **kw):
webapp2.RequestHandler.initialize(self, *a, **kw)
uid = self.read_secure_cookie('user_id')
self.user = uid and User.by_id(int(uid))
I would like to create a decorator that redirect the user to the login page if she is not logged in:
def login_required(cls):
if not self.user:
self.redirect("/login")
#login_required
class Test(MainHandler)
def get(self):
self.write("this will only display if I am logged in")
When I tried the example abode, I get 'NameError: name 'login_required' is not defined'
What am I missing?
I found this page useful in order to understand how decorators work: http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/
Your decorator needs to call the handler after performing whatever task it needs to. Here is a variation of my current login_required decorator definition:
def login_required(handler):
def check_login(self, *args, **kwargs):
userToken = auth.get_auth().get_user_by_session()
if not userToken:
logging.info('No user found for session: login required')
return self.redirect(LOGIN_URL, abort=False)
return handler(self, *args, **kwargs) # Call the handler method
return check_login
The decorator in this case is applied to the instance method, not the class ie:
class Test(MainHandler)
#login_required
def get(self):
...
I'm trying to implement a decorator that authenticates the user's token before granting access to a function. My current implementation is kind of wonky in that I need to do two queries since I can't get locals in the decorator. Is there a better way to do this?
def require_auth(func):
print 'require_auth'
#wraps(func)
def inner():
if 'token' in request.json:
token = request.json['token']
session = Session()
for instance in session.query(SQLTypes.User).filter(SQLTypes.User.token==token):
auth_user = instance.username
try:
auth_user
print 'authenticated!'
except NameError:
abort(401)
else:
abort(401)
return func()
return inner
#app.route('/st/projects', methods=['POST'])
#require_auth
def post_project():
session = Session()
for instance in session.query(SQLTypes.User).filter(SQLTypes.User.token==request.json['token']):
auth_user = instance.username
# do something with auth_user
session.close()
You can store your authenticated user in flask.g:
from flask import g
# ...
def require_auth(func):
# ...
for instance in session.query(SQLTypes.User).filter(SQLTypes.User.token==token):
g.auth_user = instance.username
try:
g.auth_user
print 'authenticated!'
except AttributeError:
abort(401)
# ...
Then in your view function you can access the user as g.auth_user.
I would like to store some information at the "request scope" when using google app engine (python). What I mean by this is that I would like to initialize some information when a request is first received, and then be able to access it from anywhere for the life of the request (and only from that request).
An example of this would be if I saved the current user's name at request scope after they were authenticated.
How would I go about doing this sort of thing?
Thanks!
A pattern used in app engine itself seems to be threading.local which you can grep for in the SDK code. Making os.environ request local is done like that in runtime/request_environment.py for example.
A rough example:
import threading
class _State(threading.local):
"""State keeps track of request info"""
user = None
_state = _State()
From elsewhere you could authenticate early on in handler code.
from state import _state
if authentication_passed:
_state.user = user
and provide convenience that can be used in other parts of your code
from state import _state
def get_authenticated_user():
user = _state.user
if not user:
raise AuthenticationError()
return user
You need something like this:-
class BaseHandler(webapp2.RequestHandler):
#A function which is useful in order to determine whether user is logged in
def initialize(self, *a, **kw):
#Do the authentication
self.username = username
class MainHandler(BaseHandler):
def get(self):
print self.username
Now if you inherit BaseHandler class all the request will first go through the initialize method of BaseHandler class and since in the BaseHandler class you are setting the username
and MainHandler inherits form BaseHandler you will have the self.username defined and all the request wil go through initialize method.