How can I require authentication for anything under /admin path? - python

I'm using Flask and I'd like to protect everything under /admin path.
How can I do that? I'm sure there's a better way than checking for the session in every function.

The most straightforward way to do this, I think, is to use a Blueprint similar to how it is described in this snippet. Then you can have some code that will run before each request when the URL starts with /admin, and within that code you can do your authentication.

The obvious way would be to write a decorator that tests the session, and redirects to another page if the authentication fails. I don't know how much python you know, but a decorator is a function that takes a function and returns another function. Basically, it's a function modifier. Here's a decorator that should show you the way to writing your own to check the session:
import functools
def check_session(view):
#functools.wraps(view)
def inner(*args, **kwargs):
if <test for auth>:
return view(*args, **kwargs)
else:
return flask.redirect("/")
return inner
As you can see, we have a function that takes the view function, and then defines a new function called inner which checks for authentication, and if it succeeds, calls the original view. The line #functools.wraps(view) is an example of using a decorator; the functools.wraps decorator gives the function it is wrapping the properties of the function that it is given as it's first argument. To use this decorator, apply it to your views as such:
#app.route("/admin")
#check_session
def admin_view():
return "Top secret"
Any user who fails the authentication check will now be redirected away, and users who do will be able to see the view as usual. Decorators are applied in a bottom to top order, so make sure that you put it after any other decorators that do function registration (i.e. #app.route).

Related

Get URL parameter inside prepare() function, instead of get() / post()

I am using tornado and I declared a RequestHandler with a single parameter like this:
class StuffHandler(RequestHandler):
def get(self, stuff_name):
...
app = Application([
(r'/stuff/(.*)/public', StuffHandler)
])
Now I added another handler for '/stuff/(.*)/private', which requires the user to be authenticated:
class PrivateStuffHandler(RequestHandler):
#tornado.web.authenticated
def get(self, stuff_name):
...
This of course will cause get_current_user() to be called before get(). The problem is that, in order for get_current_user() to run, I need to know the stuff_name parameter.
So I thought that I may use the prepare() or the initialize() method, which is called before get_current_user(). However, I can't seem to access stuff_name from those methods. I tried putting stuff_name as a parameter but it didn't work, then I tried calling self.get_argument("stuff_name") but it didn't work either.
How do I access an URL parameter from the prepare() method?
I think you can use self.request.path to get the full path, then achieve the value in path which you need.
In the end, I asked straight to Tornado developers and a helpful user made me notice that there's self.path_args and self.path_kwargs available from anywhere in the class.
So, from the prepare() method (or even the get_current_user() method), I can do:
stuff_name = self.path_args[0]

What does a Python decorator do, and where is its code? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Understanding Python decorators
What does a Python decorator do? And where can I see the codes that are running when I add a decorator to a method?
For example, when I add #login_required at the top of a method, does any code replace that line? How exactly does this line check the user session?
when I add #login_required at the top of a method, does any code replace that line?
Kind of. Adding #login_required before your view function has the same effect as doing this:
def your_view_function(request):
# Function body
your_view_function = login_required(your_view_function)
For explanations of decorators in Python, see:
http://www.python.org/dev/peps/pep-0318/
http://wiki.python.org/moin/PythonDecorators#What_is_a_Decorator
So decorator functions accept an original function, and return a function that (probably) calls the original function, but does something else too.
In the case of login_required, I think it checks the request object passed to view functions to see if the user is authenticated.
A decorator is in effect a function wrapping another function or class. The function behind the decorator in your case is named login_required. Look in your imports to find it.
A decorator is a function which wraps another function. Say you have a function f(x) and you have a decorator h(x), the decorator function takes as argument your function f(x) and so in effect what you will have is a new function h(f(x)). It makes for cleaner code as for instance in your login_required, you do not have to put in the same code to test if a user is logged in rather you can wrap the function in a login_required function so that such a function is called only if the user is logged in. Study this snippet below
def login_required(restricted_func):
"""Decorator function for restricting access to restricted pages.
Redirects a user to login page if user is not authenticated.
Args:
a function for returning a restricted page
Returns:
a function
"""
def permitted_helper(*args, **kwargs):
"""tests for authentication and then call restricted_func if
authenticated"""
if is_authenticated():
return restricted_func(*args, **kwargs)
else:
bottle.redirect("/login")
return permitted_helper

Using #ndb.tasklet or #ndb.synctasklet in Google App Engine

I have a POST method which calls a few tasklets. These tasklets do have yields in them, and I do have some x.put_async() in my code. So I don't want it to return before all the async stuff is done. So I decorated all my tasklets, which are just small functions with #ndb.tasklet. Also, on top of my POST method, I have:
#ndb.toplevel
def post(self):
However, in the documentation it states:
But if a handler method uses yield, that method still needs to be
wrapped in another decorator, #ndb.synctasklet; otherwise, it will
stop executing at the yield and not finish.
Indeed my method has a yield. It's already wrapped in #ndb.tasklet. Do I replace this with #ndb.synctasklet or do I use both (if so how would I use both)?
Also, see this thread which has some relevance. I too noticed an issue where my request would return without any output, but is un-reproducible. It happens every 15 minutes or so of constant use. I had app = ndb.toplevel(webapp2.WSGIApplication([..]) only, but now I've added #ndb.toplevel to the main POST methods, but the issue still persists.
Should I put #ndb.tasklet on top of methods that have just put_async()'s too? (Should I put it on top of every method just to be safe? What are the downsides to this?)
Regarding the handler and using #ndb.toplevel and #ndb.synctasklet:
The way I understood it was that you need to use both #ndb.synctasklet and #ndb.toplevel on the handler. All the sub-tasklets only need the #ndb.tasklet decorator. e.g.
class Foo(ndb.Model):
name = ndb.StringProperty()
#ndb.tasklet
def my_async(self):
....
#do something else that yields
raise ndb.Return("some result")
#ndb.toplevel
#ndb.synctasklet
def post(self):
foo = Foo(name="baz")
yield foo.put_async()
yield foo.my_async()
....
However. looking at the source, it appears that #ndb.toplevel is actually a synctasklet anyway:
def toplevel(func):
"""A sync tasklet that sets a fresh default Context.
Use this for toplevel view functions such as
webapp.RequestHandler.get() or Django view functions.
"""
Running a small test with yields in the handler and decorated with #ndb.toplevel still seems to work, and appears that you can remove #ndb.synctasklet from the handler.
Regarding whether you should include #ndb.tasklet on methods that call put_async():
If you're not yielding on the put_async(), then you don't need to include #ndb.tasklet on the surrounding method (#ndb.toplevel will handle getting the results from the put_async())

How do I implement two decorators in Python both of which would eventually want to call the calling function

I am trying to simply my Web application handlers, by using Python decorators.
Essentially I want to use decorators to abstract code that checks for authenticated sessions and the other that checks to see if the cache provider (Memcache in this instance) has a suitable response.
Consider this method definition with the decorators:
#auth.login_required
#cache.clear
def post(self, facility_type_id = None):
auth.login_required checks to see if the user is logged in, otherwise returns an appropriate error message, or executes the original function.
cache.clear would check to to see if the cache has a particular key and drop that, before it executes the calling method.
Both auth.login_required and cache.clear would want to eventually execute the calling method (post).
From what I've read both, doing what I am doing now would execute the calling method (post) twice.
My question, how do I chain decorators that end up executing the calling method, but ensure that it's only called once.
Appreciate any pointers and thanks for your time.
Each successive decorator receives the previously wrapped function, so the function itself only gets called once at the end of the chain. Here's a simple example:
def dec1(f):
def wrapped():
print 'dec1'
return f()
return wrapped
def dec2(f):
def wrapped():
print 'dec2'
return f()
return wrapped
#dec2
#dec1
def spam(): print 'spam'
>>> spam()
dec2
dec1
spam
You didn't understand how decorators work.
The two decorators are already "sequenced". The outer one will receive as function to act on an already decorated function. The inner function is not going to be called twice.

Help with authorization and redirection decorator in python (pylons)

I'm trying to write a simple decorator to check the authentication of a user, and to redirect to the login page if s/he is not authenticated:
def authenticate(f):
try:
if user['authenticated'] is True:
return f
except:
redirect_to(controller='login', action='index')
class IndexController(BaseController):
#authenticate
def index(self):
return render('/index.mako' )
But this approach doesn't work. When a user is authenticated, everything is fine. But when the user is not authenticated, redirect_to() doesn't work and I am given this error:
HTTPFound: 302 Found Content-Type: text/html; charset=UTF-8 Content-Length: 0 location: /login
Thank for your help!
i don't know pylons, but it seems the way you wrote your decorator is not good.
a decorator is a callable which must return a callable. the decorator is called at the moment the function is defined, and it should return a callable (generally a function) which will be called in place of the function being decorated.
in your sample, your decorator returns a callable only if the user is authenticated at the moment the index() function is defined.
try rewriting it this way:
def authenticate(func):
def call(*args, **kwargs):
if user['authenticated'] is True:
return func(*args,**kwargs)
else:
return redirect_to(controller='login', action='index')
return call
here, authenticate() defines an inner function, which is returned in place of the function it decorates. now when you decorate a function using this decorator:
#authenticate
def index(self):
return render('/index.mako' )
this means that each time you call index(), you are in fact calling the inner function declared in your decorator.
you should note that: due to the way functions are defined in python, the function object returned by the decorator still remembers the value of arguments of the function in which it was defined. call() still knows about the argument func which was passed when the decorator was called. (this is called a closure)
decorators are difficult to understand although they are not complicated. you should search google for a tutorial on decorators: there are plenty of them which gives a very nice understanding of the concept, far much clearer than the python documentation.

Categories

Resources