Restricting access to certain areas of a flask view function by role?
flask, python, roles
Solution
To actually answer your question. You should make the `admin_only` function a decorator and decorate the `admin` view method. The reason it does not redirect now is because you are not returning the redirect from the view.
def admin():
ret = admin_only()
if( not ret ):
return ret
....
That should fix your current issue, but it is not ideal and the functionality you wish should be moved to a decorator.
I also recommend the following:
Take a look at Flask-Principal it provides the ability to assign roles to users and then restrict access based on these roles to your views.
Along with Flask-Principal take a look at Flask-Security as it provides many useful security related Flask extensions and just makes it easier to use.
Example use:
@roles_required( "admin" )
def website_control_panel():
return "Only Admin's can see this."
Will ONLY allow users with the role `admin` attached to their account. Another use case is to allow a user to have one of many roles which can be specified with the `roles_accepted` and can be used as following:
@roles_accepted( "journalist", "editor" )
def edit_paper():
return render_template( "paper_editor.html", ... )
Will only allow users that have at least one of the `journalist` or `editor` roles tied to their account.
Problem
I wrote this, which seems to work just fine: ``` @app.route('/admin', methods=['GET','POST']) @login_required def admin(): if not current_user.role == ROLE_ADMIN: flash('You do not have access to view this page.') return redirect(url_for('index')) ...the rest of my code... ``` While trying to simplify things since I don't want to add these 3 lines to every area I want only visible to admins, I tried to put it in a function like so: ``` def admin_only(): if not current_user.role == ROLE_ADMIN: flash('You do not have access to view this page.') return redirect(url_for('index')) ``` and then put in my view function: ``` @app.route('/admin', methods=['GET','POST']) @login_required def admin(): admin_only() ...the rest of my code.... ``` However this doesn't work as I expected. I get the flashed message, but it does not redirect like I thought it would. So, two questions: - Why doesn't the returned redirect work? - Is there a better way to implement this functionality?