{"id":7893,"library":"accesscontrol","title":"AccessControl Security Framework for Zope","description":"AccessControl is the foundational security framework for the Zope application server, providing core components for authentication, authorization, and permission management within Zope Object Database (ZODB) applications. It defines security policies, user management interfaces, and permission checking mechanisms. The current version is 7.3, and it follows the release cadence of the wider Zope ecosystem, with stable updates aligning with Zope 5+ development.","status":"active","version":"7.3","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/AccessControl","tags":["zope","security","authorization","authentication","permission-management"],"install":[{"cmd":"pip install accesscontrol","lang":"bash","label":"Install via pip"}],"dependencies":[{"reason":"Provides core Zope interface definitions, crucial for AccessControl's design.","package":"zope.interface","optional":false},{"reason":"Used for object location and path information, which can be relevant in security context resolution.","package":"zope.location","optional":false},{"reason":"AccessControl builds upon and integrates with zope.security for defining and enforcing security policies.","package":"zope.security","optional":false}],"imports":[{"symbol":"setSecurityManager","correct":"from AccessControl.SecurityManagement import setSecurityManager"},{"symbol":"getSecurityManager","correct":"from AccessControl.SecurityManagement import getSecurityManager"},{"note":"UnrestrictedUser is a User type, not part of SecurityManagement.","wrong":"from AccessControl.SecurityManagement import UnrestrictedUser","symbol":"UnrestrictedUser","correct":"from AccessControl.User import UnrestrictedUser"},{"note":"Commonly imported Zope permission constants.","symbol":"view","correct":"from AccessControl.Permissions import view"}],"quickstart":{"code":"import os\nfrom AccessControl.SecurityManagement import setSecurityManager, getSecurityManager\nfrom AccessControl.User import UnrestrictedUser\nfrom AccessControl.Permissions import view as ViewPermission\n\n# 1. Define a mock Security Manager and User for demonstration\n# In a real Zope app, these would be provided by the Zope environment.\nclass MockUser(UnrestrictedUser):\n    def __init__(self, id, password, roles, domains, permissions=None):\n        super().__init__(id, password, roles, domains)\n        self._permissions = permissions if permissions is not None else {}\n\n    def getRoles(self):\n        return self._roles\n\n    def has_permission(self, permission_name, context):\n        # Simplified check: Manager role allows everything, otherwise check specific permissions.\n        if 'Manager' in self.getRoles():\n            return True\n        return permission_name in self._permissions.get(context.__class__.__name__, [])\n\nclass MockSecurityManager:\n    def __init__(self, user):\n        self._user = user\n\n    def getUser(self):\n        return self._user\n\n    def checkPermission(self, permission_name, context_object):\n        # In a real Zope app, this involves complex role/permission mappings.\n        return self._user.has_permission(permission_name, context_object)\n\n    def validate(self, granted_roles, context_object, permission_name):\n        # Simplified for demonstration. Real method involves deep Zope security context.\n        return self._user.has_permission(permission_name, context_object)\n\n# 2. Define a mock context object that can be secured\nclass Document:\n    def __init__(self, name):\n        self.name = name\n    def __repr__(self):\n        return f\"<Document: {self.name}>\"\n\n# 3. Create mock users with different roles and permissions\nadmin_user = MockUser('admin', 'pwd', ['Manager'], 'all', permissions={'Document': [ViewPermission, 'Edit']})\neditor_user = MockUser('editor', 'pwd', ['Editor'], 'local', permissions={'Document': ['Edit']})\nviewer_user = MockUser('viewer', 'pwd', ['Viewer'], 'local', permissions={'Document': [ViewPermission]})\n\n# 4. Create a document to test permissions against\nmy_document = Document(\"Secret Report\")\n\nprint(\"--- Admin User Context ---\")\nsetSecurityManager(MockSecurityManager(admin_user))\nsm = getSecurityManager()\ncurrent_user = sm.getUser()\nprint(f\"Current User: {current_user.getUserName()} (Roles: {current_user.getRoles()})\")\nprint(f\"Can '{ViewPermission}' on {my_document}? {sm.checkPermission(ViewPermission, my_document)}\")\nprint(f\"Can 'Edit' on {my_document}? {sm.checkPermission('Edit', my_document)}\")\n\nprint(\"\\n--- Viewer User Context ---\")\nsetSecurityManager(MockSecurityManager(viewer_user))\nsm = getSecurityManager()\ncurrent_user = sm.getUser()\nprint(f\"Current User: {current_user.getUserName()} (Roles: {current_user.getRoles()})\")\nprint(f\"Can '{ViewPermission}' on {my_document}? {sm.checkPermission(ViewPermission, my_document)}\")\nprint(f\"Can 'Edit' on {my_document}? {sm.checkPermission('Edit', my_document)}\")\n\nprint(\"\\n--- Editor User Context ---\")\nsetSecurityManager(MockSecurityManager(editor_user))\nsm = getSecurityManager()\ncurrent_user = sm.getUser()\nprint(f\"Current User: {current_user.getUserName()} (Roles: {current_user.getRoles()})\")\nprint(f\"Can '{ViewPermission}' on {my_document}? {sm.checkPermission(ViewPermission, my_document)}\")\nprint(f\"Can 'Edit' on {my_document}? {sm.checkPermission('Edit', my_document)}\")\n\n# In a real Zope app, you might restore the default security manager or a different one\n# setSecurityManager(None) # Clears the thread-local manager","lang":"python","description":"This quickstart demonstrates how to set a security manager and check permissions using AccessControl. As AccessControl is deeply integrated with Zope, this example uses mock objects to simulate a Zope environment and show the core API (`setSecurityManager`, `getSecurityManager`, `checkPermission`). In a live Zope application, the Zope server handles the lifecycle and instantiation of these security components."},"warnings":[{"fix":"Upgrade Python environment to 3.10+ or use an older AccessControl version compatible with your Python version (e.g., AccessControl 6.x for Python 3.9, 5.x for Python 3.8).","message":"AccessControl versions 7.x require Python 3.10 or newer. Users migrating from older Python 3 versions (e.g., 3.8, 3.9) or Python 2 will encounter incompatibility errors.","severity":"breaking","affected_versions":"<7.0"},{"fix":"Ensure you are developing within a Zope application environment or prepare a comprehensive mock setup that simulates Zope's security context, object acquisition, and ZODB integration.","message":"AccessControl is designed specifically for Zope applications and is tightly coupled with the Zope Object Database (ZODB) and its request lifecycle. It is not a standalone, general-purpose security library (e.g., like Flask-Security or Django-Auth) and attempting to use it outside a proper Zope context will require extensive mocking or lead to unexpected behavior.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Avoid using `UnrestrictedUser` in user-facing production code. Instead, define specific user roles and permissions, and ensure security contexts are correctly established for authenticated users with appropriate privileges.","message":"Using `AccessControl.User.UnrestrictedUser` in production code can be a significant security risk. As its name implies, this user bypasses all permission checks, effectively granting full administrative access. It is primarily intended for testing, bootstrapping, or highly controlled administrative scripts.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"For standard Zope installations using ZODB, import user-related classes from `OFS.User` (e.g., `from OFS.User import UserFolder`) or refer to your specific user management product. If creating custom users, implement `AccessControl.interfaces.IUser`.","cause":"Attempting to import a concrete user class directly from `AccessControl.User`. This module primarily defines interfaces and base classes, not specific user implementations for ZODB.","error":"ImportError: cannot import name 'User' from 'AccessControl.User'"},{"fix":"1. Verify the active user's roles (`getSecurityManager().getUser().getRoles()`). 2. Check the permissions assigned to those roles on the specific object or its parent containers through Zope's management interface. 3. Ensure a security manager is correctly set (`setSecurityManager()`) for the current request/thread.","cause":"The current authenticated user (or anonymous user) in the security context lacks the necessary permission to perform the requested action on the target object.","error":"Unauthorized: You are not authorized to access this resource. (or similar 'Insufficient privileges')"},{"fix":"Explicitly set a security manager using `AccessControl.SecurityManagement.setSecurityManager(my_security_manager_instance)` before performing security-sensitive operations. In a Zope application, this is typically handled automatically by the Zope request lifecycle.","cause":"`getSecurityManager()` is returning `None` because no security manager has been established for the current thread or context. `AccessControl` relies on a thread-local security manager to be present.","error":"AttributeError: 'NoneType' object has no attribute 'checkPermission' (or similar errors when security manager is missing)"}]}