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)
Within the __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.