How to Mock a Permissions Policy in Python
A lightweight Python class that simulates a browser Permissions-Policy header by tracking allowed/ denied feature permissions with get, set, reset, and bulk operations.
Python code
45 linesclass PermissionsPolicy:
def __init__(self):
self._features = {
"geolocation": "self",
"camera": "self",
"microphone": "self",
"payment": "self",
"usb": "self",
}
def get_feature_policy(self, feature):
return self._features.get(feature, "none")
def set_feature_policy(self, feature, policy):
if feature in self._features:
self._features[feature] = policy
return True
return False
def reset_defaults(self):
for feature in self._features:
self._features[feature] = "self"
return "reset complete"
def allow_all(self):
for feature in self._features:
self._features[feature] = "*"
return "all features allowed"
def deny_all(self):
for feature in self._features:
self._features[feature] = "none"
return "all features denied"
if __name__ == "__main__":
pp = PermissionsPolicy()
print(f"Initial camera policy: {pp.get_feature_policy('camera')}")
pp.set_feature_policy("camera", "none")
print(f"Updated camera policy: {pp.get_feature_policy('camera')}")
pp.allow_all()
print(f"After allow_all, usb policy: {pp.get_feature_policy('usb')}")
pp.deny_all()
print(f"After deny_all, payment policy: {pp.get_feature_policy('payment')}")
pp.reset_defaults()
print(f"After reset, geolocation policy: {pp.get_feature_policy('geolocation')}")
Output
Initial camera policy: self
Updated camera policy: none
After allow_all, usb policy: *
After deny_all, payment policy: none
After reset, geolocation policy: self
How it works
The PermissionsPolicy class stores feature permissions in a dictionary, defaulting to "self" for all five features. get_feature_policy uses .get so unknown features return "none" instead of raising a KeyError. set_feature_policy validates the feature name before updating, ensuring only known features can be changed. The bulk methods (allow_all, deny_all, reset_defaults) iterate the same dict to enforce uniform policies with a single call. This design mirrors the semantics of the HTTP Permissions-Policy header, where each feature has a single allowlist value.
Common mistakes
- Forgetting that unknown features return 'none', which can mask typos in feature names.
- Using 'allow'/'deny' strings instead of the header-compatible '*', 'self', or 'none'.
- Assuming `set_feature_policy` updates an unknown feature instead of returning False.
Variations
- Read feature defaults from a JSON config file using `json.load`.
- Implement a `to_header()` method that serializes the policy to an actual Permissions-Policy header string.
Real-world use cases
- Unit-testing middleware that validates incoming HTTP requests against an allowed-list of browser features.
- Simulating feature-flag behavior in a test suite without launching a real browser engine.
- Generating a consistent Permissions-Policy header for a web app's configuration based on environment variables.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.