📖 Scenario: You are building a simple Flask web app where some pages should only be accessible to users with certain roles, like 'admin' or 'editor'. You want to create a decorator that checks if the current user has the required role before allowing access.
🎯 Goal: Create a Flask decorator called role_required that takes a role name as an argument and restricts access to routes based on the user's role stored in g.user_role.
📋 What You'll Learn
Create a Flask app with a route
Create a decorator function called role_required that accepts a role string
Check the current user's role from g.user_role
Return a 403 Forbidden response if the user does not have the required role
Apply the decorator to a route to restrict access
💡 Why This Matters
🌍 Real World
Role-based access control is common in web apps to protect sensitive pages and actions. This decorator pattern helps keep your code clean and reusable.
💼 Career
Understanding decorators and access control is important for backend web development roles, especially when working with Flask or similar frameworks.
Progress0 / 4 steps
1
Set up Flask app and user role
Import Flask and g from flask. Create a Flask app called app. Set g.user_role to the string 'editor' inside a function called before_request decorated with @app.before_request.
Flask
Hint
Use @app.before_request to run code before each request. Inside that function, set g.user_role = 'editor'.
2
Create the role_required decorator function
Define a function called role_required that takes a parameter role. Inside it, define a nested function decorator that takes a function f. Inside decorator, define a wrapper function wrapper that checks if g.user_role equals role. If not, return a 403 response using return 'Forbidden', 403. Otherwise, call and return f(). Use functools.wraps(f) to preserve function metadata. Return wrapper from decorator, and return decorator from role_required. Import functools at the top.
Flask
Hint
Remember to import functools and use @functools.wraps(f) on the wrapper function. The decorator should check g.user_role against the required role.
3
Create a protected route using the decorator
Create a route /admin using @app.route('/admin'). Define a function admin_page that returns the string 'Welcome Admin'. Decorate admin_page with @role_required('admin') to restrict access to users with the 'admin' role.
Flask
Hint
Use @app.route('/admin') and decorate the function with @role_required('admin'). The function should return 'Welcome Admin'.
4
Add a public route without role restriction
Create a route /public using @app.route('/public'). Define a function public_page that returns the string 'Welcome Public'. This route should not have any role restrictions or decorators.
Flask
Hint
Just create a normal route /public without any decorators. The function should return 'Welcome Public'.
Practice
(1/5)
1. What is the main purpose of a decorator that checks user roles in a Flask app?
easy
A. To log user activity without restrictions
B. To speed up the execution of functions
C. To change the user role dynamically
D. To restrict access to certain functions based on user roles
Solution
Step 1: Understand the role of decorators in Flask
Decorators wrap functions to add extra behavior, like checking conditions before running the function.
Step 2: Identify the purpose of role checking
Role checking ensures only users with the right permissions can access certain parts of the app.
Final Answer:
To restrict access to certain functions based on user roles -> Option D
Quick Check:
Role check decorator = restrict access [OK]
Hint: Decorators add checks before function runs [OK]
Common Mistakes:
Thinking decorators change user roles
Assuming decorators speed up code
Confusing logging with access control
2. Which of the following is the correct syntax to define a decorator that requires a role named 'admin' in Flask?
easy
A. @require_role(admin)\ndef admin_panel():\n pass
B. def require_role('admin'):\n def admin_panel():\n pass
C. @require_role('admin')\ndef admin_panel():\n pass
D. @require_role['admin']\ndef admin_panel():\n pass
Solution
Step 1: Recognize decorator syntax in Python
Decorators use @ followed by the decorator function call with parentheses if it takes arguments.
Step 2: Check correct argument passing
The role name 'admin' must be passed as a string inside parentheses.
Final Answer:
@require_role('admin')\ndef admin_panel():\n pass -> Option C
Quick Check:
Decorator with parentheses and string argument = correct [OK]
Hint: Decorator with argument uses parentheses and quotes [OK]
Common Mistakes:
Missing parentheses for decorator with arguments
Passing role without quotes
Using square brackets instead of parentheses
3. Given this decorator code snippet, what will be printed when a user with role 'user' tries to access the decorated function?
A. Missing return statement before func call inside wrapper
B. Incorrect use of *args and **kwargs
C. current_user.role should be current_user.roles
D. Decorator should not have nested functions
Solution
Step 1: Check the wrapper function's return behavior
The wrapper calls func(*args, **kwargs) but does not return its result, so the decorated function returns None.
Step 2: Confirm correct fix
Adding 'return' before func call ensures the wrapper returns the function's output properly.
Final Answer:
Missing return statement before func call inside wrapper -> Option A
Quick Check:
Always return function result in wrapper [OK]
Hint: Wrapper must return the wrapped function's result [OK]
Common Mistakes:
Forgetting to return function output
Misusing argument unpacking
Incorrect attribute name for user role
5. You want to create a Flask decorator that allows access if the user role is either 'admin' or 'editor'. Which of these decorator implementations correctly achieves this?
hard
A. def require_roles(*roles):
def decorator(func):
def wrapper(user_role):
if user_role in roles:
return func()
return 'Access Denied'
return wrapper
return decorator
@require_roles('admin', 'editor')
def edit_page():
return 'Edit Page'