I am using Pone 5.2.2 and want to achieve the following:
I've created a view every user can call (
permission="zope.Public"). That view retrieves some data through a GET request. Dependent on its value I want to call a different view in the context of an other user. The view to be called has the form of an usual HTTP request but the path is relative to the portal root.
Assume I want to call the view http://localhost:8080/mysite/secret.png/@@download in the context of the user "nicolas" but the original call is just an anonymous user with right GET request. How can I respond with
secret.png as long as
nicolas has the right permissions to see it?
I already tried this:
from plone import api from AccessControl import ClassSecurityInfo, getSecurityManager from AccessControl.SecurityManagement import newSecurityManager, setSecurityManager from AccessControl.User import Super class UnrestrictedUser(Super): """Unrestricted user that still has an id. """ def getId(self): """Return the ID of the user. """ return self.getUserName() def executeAsUser(user, function, *args, **kwargs): sm = getSecurityManager() portal = api.portal.get() try: try: tmp_user = UnrestrictedUser( sm.getUser().getId(), '', api.user.get_roles(user = user), '' ) # Wrap the user in the acquisition context of the portal tmp_user = tmp_user.__of__(portal.acl_users) newSecurityManager(None, tmp_user) # Call the function return function(*args, **kwargs) except: # If special exception handlers are needed, run them here raise finally: # Restore the old security manager setSecurityManager(sm)
__call__ method of my view I then write this:
user = api.user.get(userid = 'nicolas') if not user: self.request.response.setStatus(401, reason = "Unauthorized. Access denied.", lock = True) return '' portal = api.portal.get() return executeAsUser( user, lambda x: portal.restrictedTraverse(x).__call__(), 'secret.png/@@download')
But this does not seem to work. I always get redirected to the login_form. I also tried an
unrestrictedTraverse() without the
executeAsUser but it also redirected me to the login form again.
In principle I want to make the outer view transparent to the user. I should simply call the other view in the context of a given user.