Flask python assertion error: unimplemented method 'GET' - python

Can someone please explain to me the difference between these two blocks of code. The first one works while the latter throws the error which I've indicated in the title.
def login_required(method):
#functools.wraps(method)
def wrapper(*args, **kwargs):
if 'username' in flask.session:
return method(*args, **kwargs)
else:
flask.flash("A login is required to see the page!")
return flask.redirect(flask.url_for('index'))
return wrapper
AND
def login_required(method):
#functools.wraps(method)
def wrapper(*args,**kwargs):
if "username" in flask.session:
return method(*args,**kwargs)
else:
flask.flash("A login is required to see the page!")
return flask.redirect(flask.url_for('index'))
return wrapper

In the first code sample, you correctly return the wrapper function at the end of the login_required function.
In the second code sample you've got the return wrapper inside the wrapper function itself. Just de-dent that last line and you should be all set.

Related

Flask custom decorator not functioning as expected

I'm using Flask and have two decorators that I'm trying to use on certain routes to be more Pythonic, prevent code reuse, and improve readability.
The first of these are just checks to see if the user is logged in else redirect user to the login page. This works fine.
After this I check for the user 'class' (Admin, Manager, Standard User, etc), however this one isn't working and I'm not sure what is missing.
From the routes.py:
#app.route('/user/user-account.html', methods=['GET', 'POST'])
#login_required
def cna_account():
if valid_user() == True:
result = get_user_account()
return render_template('user/user-account.html', result=result)
else:
return redirect(url_for('index'))
#login_reqiured works fine, here is the code:
#wraps(f)
def wrap(*args, **kwargs):
if 'logged_in' in session:
return f(*args, **kwargs)
else:
return redirect(url_for('index'))
return wrap
What I tried for the other decorator that doesn't work:
def valid_user(f):
''' Makes sure that only Base Users can view the Base User pages '''
#wraps(f)
def wrap(*args, **kwargs):
if 'access' in session and session['access'] == 'c':
return f(*args, **kwargs)
else:
return redirect(url_for('index'))
These are stored in a separate module that is imported in routes.py, the only thing I can guess is perhaps the session isn't being carried across even though it's included from flask in the module and routes, but again I'm not sure how this would be remedied.
What I'm trying to do with it is: have the routes that use both decorators and don't require the if valid_user() == True check. Instead it should function and look like:
#app.route('/user/user-account.html', methods=['GET', 'POST'])
#login_required
#valid_user
def cna_account():
result = get_user_account()
return render_template('user/user-account.html', result=result)
Any help on what I'm missing here? Do I need to pass the session variable as an argument to #valid_user? I tried that a few different ways and still had it throw errors.
Much appreciated!
You need to return the inner function wrap in valid_user:
def valid_user(f):
#wraps(f)
def wrap(*args, **kwargs):
if 'access' in session and session['access'] == 'c':
return f(*args, **kwargs)
return redirect(url_for('index'))
return wrap
While it is perfectly valid to not return anything from an outer decorator function, bear in mind that the wrapped function is passed to the wrapper at run time, thus, the returned value will be None:
def foo(f):
print("inside decorator with '{}'".format(f.__name__))
def inner():
return 10
#foo
def bar():
return 'in bar'
"inside decorator with 'bar'"
>>>bar()
Traceback (most recent call last):
File "", line 1, in
TypeError: 'NoneType' object is not callable

passing arguments between multiple decorators

I am using two decorators to decorate a function "add_user", the first one #auth_user authenticates the logged in user via json web token request headers and returns the user's information as an argument "user_info" back to the decorated function add_user. The second decorator #has_permission is supposed to check whether or not the user has permissions on the requested resource. I wanted to pass the user's information returned as user_info by #auth_user to #has_permission but don't know how to do that, here is the code so far:
#has_permission
#auth_user
def add_user(user_info):
"""
do something
"""
return None
The decorators:
def auth_user(f):
#wraps(f)
def wrapper(*args, **kwargs):
data = jwt.decode(request.headers['some-access-token'], some_secret_key)
try:
user_info = User.query.filter(User.id==data['user_id']).first()
except:
return jsonify({"message" : "error"}), 401
return f(user_info, *args, **kwargs)
return wrapper
and the second decorator where I want to access the user_info:
def has_permission(f):
wraps(f)
def wrapper(*args, **kwargs):
# This is where I want to access the user information instead of processing the key again #
# return some new_args ... #
return f(*args, **kwargs)
return wrapper
What is the best way to achieve this?
With some help, I managed to get this working and the main problem was the order/sequence of the decorators. In the question; #has_permission took #auth_user as an argument and #auth_user took the original function add_user as an argument like so:
has_permission(auth_user(add_user(user_info)))
This would mean that when arguments are returned, the outer most decorator #has_permission would return arguments to #auth_user and then to add_user. This meant that #has_permission could not access user_info returned by #auth_user so I modified the original function:
#auth_user
#has_permission
def add_user(user_info):
"""
do something
"""
return None
Now the decorators would be called in the correct order like this:
auth_user(has_permission(add_user(user_info)))
I also changed the way user_info was injected by #auth_user and changed it to kwargs instead of args to access it in #has_permission:
def auth_user(f):
#wraps(f)
def wrapper(*args, **kwargs):
data = jwt.decode(request.headers['some-access-token'], some_secret_key)
try:
user_info = User.query.filter(User.id==data['user_id']).first()
except:
return jsonify({"message" : "error"}), 401
kwargs['user_info'] = user_info
return f(*args, **kwargs)
return wrapper
And finally passing on the user_info to original function:
def has_permission(f):
wraps(f)
def wrapper(*args, **kwargs):
#access user info
user_info = kwargs['user_info']
return f(user_info, *args, **kwargs)
return wrapper
Hope this helps someone!

python flask protect user page

i want to protect page on python-flask, can go on this page only limited users.
I'm write this code :
def im_seller():
if not g.user.seller_fee_paid:
return redirect(url_for('account.seller_fee'))
return
#account.route('/account/seller/products.html')
#login_required
#im_seller
def seller_products():
the script not working, give this error :
TypeError: im_seller() takes no arguments (1 given)
where I'm wrong ? thanks all.
Decorators take a function and need to return a function:
from functools import wraps
def require_seller(f):
#wraps(f)
def require_seller_wrapper(*args, **kwargs):
if not g.user.seller_fee_paid:
return redirect(url_for('account.seller_fee'))
return f(*args, **kwargs)
return require_seller_wrapper
You will also want to reverse the order of require_seller and login_required so you can be sure that g.user is set:
#account.route('/account/seller/products.html')
#require_seller
#login_required
def seller_products():
return "All the seller's products"
See this answer about decorators for all the details as to the whys.
from functools import wraps
def require_seller(f):
#wraps(f)
def require_seller_wrapper(*args, **kwargs):
if not g.user.seller_fee_paid:
return redirect(url_for('account.seller_fee'))
return f(*args, **kwargs)
return require_seller_wrapper
You should use the python decorator.Link

Use decorators check user login in flask?

I defined a check user method:
from functools import wraps
def check_user(func):
#wraps(func)
def wrapper(*args, **kwargs):
if session['logged_in']:
return func(*args, **kwargs)
else:
return 'Log in'
return wrapper
#app.route('/test')
#check_user
def test():
return "Hello"
It does not work. how can I correct it?
It seems you don't know how to create decorators in python. There are many helpful answers on this question: How can I make a chain of function decorators in Python?
Below is how you can create a decorator that checks if a user is logged in.
from functools import wraps
def checkuser(func):
"""Checks whether user is logged in or raises error 401."""
#wraps(func)
def wrapper(*args, **kwargs):
if not g.user:
abort(401)
return func(*args, **kwargs)
return wrapper
The decorator above will raise a 401 error if a user is not logged in. It will return the view function otherwise.

What's wrong with my?

I have a problem with decorator. I'm trying to write my own decorator with optional argument.
This is how its done now:
def CheckPremissions(manager=1):
def wrap(func):
def wrapper(request, *args, **kwargs):
if request.user.is_anonymous():
return HttpResponseRedirect(reverse('login'))
logged_user = getRelatedWorker(request.user)
if (logged_user == None):
return HttpResponseRedirect('accounts/no_worker_error.html')
if self.manager != 0:
try:
dzial = Dzial.objects.get(kierownik=logged_user)
except Dzial.DoesNotExist:
isManager = False
else:
isManager = True
if not isManager:
return HttpResponseRedirect('accounts/denied_logged.html')
return func(request, *args, **kwargs)
return wrapper
return wrap
Code is looking good (for me), but when I use a decorator, I'm getting following error:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8080/applications/show
Django Version: 1.4.1
Python Version: 2.7.3
Traceback:
File "/home/marcin/projekt/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
188. response = middleware_method(request, response)
File "/home/marcin/projekt/lib/python2.7/site-packages/django/middleware/common.py" in process_response
94. if response.status_code == 404:
Exception Type: AttributeError at /applications/show
Exception Value: 'function' object has no attribute 'status_code'
What am I doing wrong?
I suspect you are applying the decorator incorrectly. You need to call it to specify the manager parameter:
#CheckPremissions()
def someview(request):
pass
or to specify it explicitly:
#CheckPremissions(manager=0)
def someview(request):
pass
You have a different problem in your decorator as well; you refer to self.manager in the code:
if self.manager != 0:
but this is no instance, and there is no self parameter. I think you meant:
if manager:
(where you can test for the variable to be non-zero by treating it as a boolean). Oh, and you may want to fix the spelling of the decorator; you probably meant CheckPermissions instead. :-)

Categories

Resources