Commit 93478027 authored by Jérome Perrin's avatar Jérome Perrin

patches/WSGIPublisher: backport from Zope4 👷

remaining TODO: check the diff more carefully between the monkey
patches and the version from Zope. There are also some TODO comments
inline in this patch for things that are suspicious
parent 57599970
...@@ -29,6 +29,7 @@ from six import text_type ...@@ -29,6 +29,7 @@ from six import text_type
from six.moves._thread import allocate_lock from six.moves._thread import allocate_lock
import transaction import transaction
from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import noSecurityManager
from Acquisition import aq_acquire from Acquisition import aq_acquire
...@@ -230,6 +231,10 @@ def dont_publish_class(klass, request): ...@@ -230,6 +231,10 @@ def dont_publish_class(klass, request):
request.response.forbiddenError("class %s" % klass.__name__) request.response.forbiddenError("class %s" % klass.__name__)
def validate_user(request, user):
newSecurityManager(request, user)
def get_module_info(module_name='Zope2'): def get_module_info(module_name='Zope2'):
global _MODULES global _MODULES
info = _MODULES.get(module_name) info = _MODULES.get(module_name)
...@@ -241,7 +246,7 @@ def get_module_info(module_name='Zope2'): ...@@ -241,7 +246,7 @@ def get_module_info(module_name='Zope2'):
app = getattr(module, 'bobo_application', module) app = getattr(module, 'bobo_application', module)
realm = _DEFAULT_REALM if _DEFAULT_REALM is not None else module_name realm = _DEFAULT_REALM if _DEFAULT_REALM is not None else module_name
error_hook = getattr(module,'zpublisher_exception_hook', None) error_hook = getattr(module,'zpublisher_exception_hook', None)
validated_hook = getattr(module,'zpublisher_validated_hook', None) validated_hook = getattr(module,'zpublisher_validated_hook', validate_user)
_MODULES[module_name] = info = (app, realm, _DEFAULT_DEBUG_MODE, validated_hook, error_hook) _MODULES[module_name] = info = (app, realm, _DEFAULT_DEBUG_MODE, validated_hook, error_hook)
return info return info
...@@ -309,6 +314,9 @@ def transaction_pubevents(request, response, err_hook, tm=transaction.manager): ...@@ -309,6 +314,9 @@ def transaction_pubevents(request, response, err_hook, tm=transaction.manager):
try: try:
retry = False retry = False
unauth = False
debug_exc = getattr(response, 'debug_exceptions', False)
try: try:
# Raise exception from app if handle-errors is False # Raise exception from app if handle-errors is False
# (set by zope.testbrowser in some cases) # (set by zope.testbrowser in some cases)
...@@ -339,14 +347,18 @@ def transaction_pubevents(request, response, err_hook, tm=transaction.manager): ...@@ -339,14 +347,18 @@ def transaction_pubevents(request, response, err_hook, tm=transaction.manager):
raise raise
exc_view_created = True exc_view_created = True
else: else:
# Handle exception view # Handle exception view. Make sure an exception view that
# blows up doesn't leave the user e.g. unable to log in.
try:
exc_view_created = _exc_view_created_response( exc_view_created = _exc_view_created_response(
exc, request, response) exc, request, response)
except Exception:
if isinstance(exc, Unauthorized): exc_view_created = False
# _unauthorized modifies the response in-place. If this hook # _unauthorized modifies the response in-place. If this hook
# is used, an exception view for Unauthorized has to merge # is used, an exception view for Unauthorized has to merge
# the state of the response and the exception instance. # the state of the response and the exception instance.
if isinstance(exc, Unauthorized):
unauth = True
exc.setRealm(response.realm) exc.setRealm(response.realm)
response._unauthorized() response._unauthorized()
response.setStatus(exc.getStatus()) response.setStatus(exc.getStatus())
...@@ -357,10 +369,8 @@ def transaction_pubevents(request, response, err_hook, tm=transaction.manager): ...@@ -357,10 +369,8 @@ def transaction_pubevents(request, response, err_hook, tm=transaction.manager):
tm.abort() tm.abort()
notify(pubevents.PubFailure(request, exc_info, retry)) notify(pubevents.PubFailure(request, exc_info, retry))
if retry: if retry or \
reraise(*exc_info) (not unauth and (debug_exc or not exc_view_created)):
if not (exc_view_created or isinstance(exc, Unauthorized)):
reraise(*exc_info) reraise(*exc_info)
finally: finally:
# Avoid traceback / exception reference cycle. # Avoid traceback / exception reference cycle.
...@@ -376,6 +386,7 @@ def publish(request, module_info): ...@@ -376,6 +386,7 @@ def publish(request, module_info):
request.processInputs() request.processInputs()
response = request.response response = request.response
# TODO: here is different
if debug_mode: if debug_mode:
response.debug_mode = debug_mode response.debug_mode = debug_mode
...@@ -476,6 +487,12 @@ def publish_module(environ, start_response, ...@@ -476,6 +487,12 @@ def publish_module(environ, start_response,
with load_app(module_info) as new_mod_info: with load_app(module_info) as new_mod_info:
with transaction_pubevents(request, response, err_hook): with transaction_pubevents(request, response, err_hook):
response = _publish(request, new_mod_info) response = _publish(request, new_mod_info)
# TODO: outside of load_app, because this cause
# "should not load state when connection is closed"
# if used in original place (eg. erp5_web_renderjs_ui_test:testFunctionalRJSDeveloperMode)
user = getSecurityManager().getUser()
if user is not None and user.getUserName() != 'Anonymous User':
environ['REMOTE_USER'] = user.getUserName()
break break
except TransientError: except TransientError:
if request.supports_retry(): if request.supports_retry():
...@@ -491,6 +508,7 @@ def publish_module(environ, start_response, ...@@ -491,6 +508,7 @@ def publish_module(environ, start_response,
status, headers = response.finalize() status, headers = response.finalize()
start_response(status, headers) start_response(status, headers)
# TODO: this part is slightly different
result = response.body result = response.body
if isinstance(result, _FILE_TYPES): if isinstance(result, _FILE_TYPES):
if response.stdout.getvalue(): if response.stdout.getvalue():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment