0

I am trying to build a flask app which will be having RBAC feature. For this I have written a decorator which is working fine but it can only take one argument meaning only one access level(e.g WRITE, READ, admin etc), but I want to pass multiple arguments to it. I have tried passing a list but its not taking it. I have never worked with decorators so need help with it. Thanks.

def permission_required(permission):
 def decorator(f):
 @wraps(f)
 def decorated_function(*args, **kwargs):
 if not current_user.can(permission):
 abort(403)
 return f(*args, **kwargs)
 return decorated_function
 return decorator
def admin_required(f):
 return permission_required(Permission.ADMIN)(f)

I as passing it like this:

@role_needed(Permission.VIEW), but I want to have this @role_needed(Permission.VIEW, Permission.WRITE)

My permission class is like this:

class Permission:
 VIEW = 'Vew'
 WRITE = 'Write'
 ADMIN = 'admin'
davidism
128k31 gold badges417 silver badges348 bronze badges
asked Mar 17, 2021 at 14:34
1
  • What do you mean by "its not taking it" ? Commented Mar 17, 2021 at 14:41

2 Answers 2

3

First, I'd advise that you have a look at some tutorial on decorators, they are pretty cool and you definitely need to understand the basics if you want to use flask. I personally quite like this RealPython tutorial.

Second, you have two solutions : either default second argument or argument packing.

def permission_required(permission1, permission2=None):
...

or

def permission_required(*perms):
...

I personaly way prefer the second option. Example:

def permission_required(*perms):
 def decorator(f):
 @wraps(f)
 def decorated_function(*args, **kwargs):
 for perm in perms:
 if not current_user.can(perm):
 abort(403)
 return f(*args, **kwargs)
 return decorated_function
 return decorator
answered Mar 17, 2021 at 14:57

2 Comments

Yes, you are rightthe article cleared my doubt, I wonder how come I didn't come across it before. Thanks a lot. I fixed the issue
Glad it helped ;)
1

I think you missed the point that decorators are just usual functions, taking a function in argument and another one, the later being by design a wrapper around the original one. In your case, permission_required is a decorator factory, that can be used to specialize a decorator based on input arguments. So all you need to do is to allow passing any number of arguments to your decorator factory:

def role_needed(*permissions):
 def decorator(f):
 @wraps(f)
 def decorated_function(*args, **kwargs):
 nonlocal permissions # Just to make sure `permission` is available in this scope
 # Implement here how to deal with permissions
 return f(*args, **kwargs)
 return decorated_function
 return decorator

which can be called as intended:

@role_needed(Permission.VIEW, Permission.WRITE, ...)

In the function, permissions will store the input Permission as a Python tuple object.

answered Mar 17, 2021 at 14:56

1 Comment

Thanks for the answer. Yup I missed that part that is just another python function.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.