Menu

Sign in to track your progress and unlock all features.

Theme style

Log in

Full lesson preview

Create an Access Control Decorator Checking Roles

Build a decorator factory require_roles that restricts function execution based on a user's role.

Python practice15 minDecorators FundamentalsIntermediateLast updated April 15, 2026

Problem statement

Write a decorator factory require_roles(*allowed_roles) that returns a decorator. The decorator should wrap a function and check the role of the caller before allowing execution. Behavior rules: - The wrapped function will receive a 'user' value either as the first positional argument or via the keyword argument 'user'. - A user is represented as a dict-like object with a 'role' key (e.g. {'role': 'admin'}). If the user is None or missing the 'role' key, treat them as 'guest'. - If allowed_roles is empty (no roles passed to require_roles), then the function should be accessible to everyone. - If the user's role is in allowed_roles, call the original function and return its value. - Otherwise return the string 'Access denied' and do not call the original function. Use functools.wraps to preserve metadata. Your decorator must be usable with functions that accept additional arguments beyond user.

Task

Implement a decorator that accepts allowed roles and only runs the wrapped function when the provided user has one of those roles. Support user passed as a positional first argument or as the keyword 'user'.

Examples

Basic usage

Input

require_roles('admin') @require_roles('admin') def admin_task(user): return 'admin done' admin_task({'role':'admin'})

Output

admin done

User has role 'admin', which is allowed, so the function runs and returns 'admin done'.

Input format

A function decorated with @require_roles(...) is called with a user either as the first positional argument or as the keyword 'user'.

Output format

The wrapped function's return value when allowed, or the string 'Access denied' when not allowed.

Constraints

- Do not raise exceptions for unauthorized access; return 'Access denied'. - Support an empty allowed_roles list which means allow all users. - Use functools.wraps to preserve function metadata.

Samples

Sample 1

Input

edit_article({'role':'editor'}, 'Title')

Output

edited Title

The 'editor' role is allowed to edit; the function returns the edited title message.