# Permissions Manager

> Manage user permissions with config updates.

Canonical URL: <https://datadriven.io/problems/permissions_manager>

Domain: Python · Difficulty: medium · Seniority: L5

## Problem

Given a list of permission operations, process them in order and return the list of boolean results from each 'check' operation. Operations: ['grant', user, permission] (add), ['revoke', user, permission] (remove), ['check', user, permission] (yield True/False), ['update_config', {user: [permissions]}] (replace all users' permissions wholesale).

## Worked solution and explanation

### Why this problem exists in real interviews

Processing a sequence of stateful operations tests **set-based state management** and whether you can implement a clean command dispatcher. It mirrors real IAM systems where permissions are granted, revoked, and checked.

---

### Break down the requirements

#### Step 1: Maintain a set of permissions per user

Use a dict mapping each user to a set of their current permissions.

#### Step 2: Process each operation in order

Grant adds to the set, revoke removes from the set, and check tests membership.

#### Step 3: Collect check results

Return a list of boolean results from all check operations, in order.

---

### The solution

**Set-based permission tracking with operation dispatch**

```python
def process_permissions(operations):
    permissions = {}
    results = []
    for op in operations:
        action = op[0]
        user = op[1]
        perm = op[2]
        if user not in permissions:
            permissions[user] = set()
        if action == 'grant':
            permissions[user].add(perm)
        elif action == 'revoke':
            permissions[user].discard(perm)
        elif action == 'check':
            results.append(perm in permissions[user])
    return results
```

> **Time and Space Complexity**
>
> **Time:** O(n) where n is the number of operations. Each set operation is O(1) average.
> 
> **Space:** O(u * p) where u is the number of users and p is the average number of permissions per user.

> **Interviewers Watch For**
>
> Using `set.discard()` instead of `set.remove()`. The `discard` method does not raise KeyError if the permission is not present, which makes revoke idempotent.

> **Common Pitfall**
>
> Using `set.remove()` for revoke. This raises KeyError if the permission was never granted, causing a crash on double-revoke.

---

## Common follow-up questions

- What if permissions should support hierarchical inheritance? _(Tests building a permission tree where granting 'admin' implies 'read' and 'write'.)_
- How would you add an 'update_config' operation that replaces all permissions? _(Tests clearing the set and adding the new permission set in one operation.)_
- What if operations arrive concurrently from multiple threads? _(Tests knowledge of thread-safe data structures or locking strategies.)_
- How would you audit the permission history? _(Tests appending each operation to an audit log alongside the state change.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/permissions_manager)
- [Python Interview Questions](https://datadriven.io/python-interview-questions)
- [Data Engineering Interview Prep Guide](https://datadriven.io/data-engineer-interview-prep)
- [Daily Challenge](https://datadriven.io/daily)

---

Source: DataDriven (https://datadriven.io). 100% free data engineering interview prep. Live code execution against Postgres 16, Python 3.11, and Spark sandboxes. No paywall, no premium tier, no signup gate.