Unauthorized: Not authorized to access binding: context
Sometimes when working within Zope, you'll get a lengthy traceback that ends with lines similar to the following:
Module Products.Five.browser.TrustedExpression, line 69, in trustedTraverse - __traceback_info__: (, 'render_base_tag') Module Shared.DC.Scripts.Bindings, line 180, in __getattr__ Module Shared.DC.Scripts.Bindings, line 187, in __you_lose Unauthorized: Not authorized to access binding: context
This traceback isn't very helpful; if you look at the code where the failure occurs, or even the entire stack trace, using all of the best techniques for debugging authorization errors, you'll still have a very hard time figuring out what, exactly, is triggering the error. The reason these problems are so elusive is that the error is actually raised in a completely separate area of the code than where the security violation happens. So what exactly is going on here?
First, some background info: In Zope, whenever you are coding either a TAL template or a Script (Python) object, some variables are automatically bound for use within your code. One of these is "context", which refers to the last object in the traversal chain, upon which the template or script is being rendered. The above error happens when the current user is, for some reason, able to get to the script, but the user does not actually have permission to access this context object.
For historical reasons, the situation described above does not always lead to an exception being raised. If the script doesn't ever try to use the bound "context" variable, then there isn't really a problem, and the error will never be raised. This is why the real source of the problem is so elusive; it's a lazily evaluated exception, it isn't actually brought to the user's attention until the context variable is dereferenced.
So how do we deal with this? The best trick I know of is to put a breakpoint in the code where the lazy binding occurs, in order to get detailed information about the authorization failure that is actually causing the problem. For scripts, this is in the Shared.DC.Scripts module, in the _getContext method of the Bindings class. For my current Zope checkout (Zope 2.9.8), this method looks so:
def _getContext(self): # Utility for bindcode. while 1: self = self.aq_parent if not getattr(self, '_is_wrapperish', None): parent = getattr(self, 'aq_parent', None) inner = getattr(self, 'aq_inner', None) container = getattr(inner, 'aq_parent', None) try: getSecurityManager().validate(parent, container, '', self) except Unauthorized: return UnauthorizedBinding('context', self) return self
You'll notice the try: except Unauthorized code block in there; that's what we're interested in. It is the getSecurityManager().validate(parent, container, '', self) call that is raising the exception, but we're catching it and returning an UnauthorizedBinding instance, which (possibly) triggers the error at some later point.
That's the hard part. To get the real information, you can insert a breakpoint into the code immediately after the except: Unauthorized clause, then trigger the error to hit your breakpoint. Once you're at a (pdb) prompt, you can execute the getSecurityManager() call, exactly as it is in the code, and the output should contain a traceback that is the REAL reason for the authorization failure. (Note: This traceback will be considerably more helpful if you have VerboseSecurity turned on.)
Et voila! There's still an issue to be resolved, possibly a sticky one, but at least now you've identified the actual source of the problem. Good luck!