PloneのRegistrationToolとPasswordResetToolに問題があることを発見しました
テンプレートmail_password_response.ptは、HTTPRequestが作成されていない場合でもレンダリングされます。このテンプレートは、main_templateに依存するフルフレームのPloneページです。main_templateには、実際のHTTPRequestオブジェクトの存在、つまりACTUAL_URLパラメーターに依存するビューレットがあります。
このような状況を修正するにはどうすればよいですか?結果を表示するブラウザがない場合は、明らかにmail_password_response.ptをレンダリングしないでください。しかし、HTTPRequestが「本物」であるかどうかをディープPloneコードでチェックする方法は、UI応答につながるはずです。ひどいZMImanage_xxxハックです。
問題の適切な修正は何でしょうか?RegistrationToolがテンプレートをレンダリングしないようにしているのでしょうか、それとも不完全なテストスタブのHTTPRequestオブジェクトに対してビューレットを安全にしているのでしょうか。
これは、palayout.viewlets.commonのACTUAL_URLを必要とするビューレットビットです。
class ContentViewsViewlet(ViewletBase):
@memoize
def prepareObjectTabs(self, default_tab='view', sort_first=['folderContents']):
"""Prepare the object tabs by determining their order and working
out which tab is selected. Used in global_contentviews.pt
"""
context = aq_inner(self.context)
context_url = context.absolute_url()
request_url = self.request['ACTUAL_URL']
request_url_path = request_url[len(context_url):]
if request_url_path.startswith('/'):
request_url_path = request_url_path[1:]
これは、CMFPlone RegistrationToolの違反呼び出しでmain_template.pt
あり、コンシューマーがない場合でもフルレンダリングをトリガーします。
security.declarePublic('registeredNotify')
def registeredNotify(self, new_member_id):
""" Wrapper around registeredNotify """
membership = getToolByName(self, 'portal_membership')
utils = getToolByName(self, 'plone_utils')
member = membership.getMemberById(new_member_id)
...
return self.mail_password_response(self, self.REQUEST)
サンプルトレースバック:
Error in test test_logout_smartcard (xxxtesting.ui.test_smartcard.TestSmartcard)
Traceback (most recent call last):
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 318, in run
self.setUp()
File "/Users/mikko/code/xxx-dev/src/xxx-packages/xxxtesting/xxxtesting/ui/test_smartcard.py", line 193, in setUp
self.xxx_helper.create_all()
File "/Users/mikko/code/xxx-dev/src/xxx-packages/xxxtesting/xxxtesting/xxxhelper.py", line 594, in create_all
self.create_xxx_manager("xxx_manager")
File "/Users/mikko/code/xxx-dev/src/xxx-packages/xxxtesting/xxxtesting/xxxhelper.py", line 412, in create_xxx_manager
mem.update(**data)
File "/Users/mikko/code/buildout-cache/eggs/Products.remember-1.9.1-py2.7.egg/Products/remember/content/member.py", line 653, in update
triggerAutomaticTransitions(self)
File "/Users/mikko/code/buildout-cache/eggs/Products.remember-1.9.1-py2.7.egg/Products/remember/Extensions/workflow.py", line 34, in triggerAutomaticTransitions
wf_tool.doActionFor(ob, 'trigger')
File "/Users/mikko/code/buildout-cache/eggs/Products.CMFCore-2.2.6-py2.7.egg/Products/CMFCore/WorkflowTool.py", line 241, in doActionFor
wfs, ob, action, wf.doActionFor, (ob, action) + args, kw)
File "/Users/mikko/code/buildout-cache/eggs/Products.CMFCore-2.2.6-py2.7.egg/Products/CMFCore/WorkflowTool.py", line 552, in _invokeWithNotification
res = func(*args, **kw)
File "/Users/mikko/code/buildout-cache/eggs/Products.DCWorkflow-2.2.4-py2.7.egg/Products/DCWorkflow/DCWorkflow.py", line 282, in doActionFor
self._changeStateOf(ob, tdef, kw)
File "/Users/mikko/code/buildout-cache/eggs/Products.DCWorkflow-2.2.4-py2.7.egg/Products/DCWorkflow/DCWorkflow.py", line 421, in _changeStateOf
sdef = self._executeTransition(ob, tdef, kwargs)
File "/Users/mikko/code/buildout-cache/eggs/Products.DCWorkflow-2.2.4-py2.7.egg/Products/DCWorkflow/DCWorkflow.py", line 474, in _executeTransition
script(sci) # May throw an exception.
File "/Users/mikko/code/buildout-cache/eggs/Products.ExternalMethod-2.13.0-py2.7.egg/Products/ExternalMethod/ExternalMethod.py", line 241, in __call__
return f(self.aq_parent.this(), *args, **kw)
- __traceback_info__: ((<Products.DCWorkflow.Expression.StateChangeInfo instance at 0x107492e18>,), {}, None)
File "/Users/mikko/code/buildout-cache/eggs/Products.remember-1.9.1-py2.7.egg/Products/remember/Extensions/workflow.py", line 64, in register
return obj.register()
File "/Users/mikko/code/xxx-dev/src/xxx-eggs/Products.xxxHospital/Products/xxxHospital/content/xxxUser.py", line 194, in register
BaseMember.register(self)
File "/Users/mikko/code/buildout-cache/eggs/Products.remember-1.9.1-py2.7.egg/Products/remember/content/member.py", line 718, in register
rtool.registeredNotify(self.getId())
File "/Users/mikko/code/buildout-cache/eggs/Products.CMFPlone-4.1.6-py2.7.egg/Products/CMFPlone/RegistrationTool.py", line 345, in registeredNotify
return self.mail_password_response(self, self.REQUEST)
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Shared/DC/Scripts/Bindings.py", line 322, in __call__
return self._bindAndExec(args, kw, None)
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Shared/DC/Scripts/Bindings.py", line 359, in _bindAndExec
return self._exec(bound_data, args, kw)
File "/Users/mikko/code/buildout-cache/eggs/Products.CMFCore-2.2.6-py2.7.egg/Products/CMFCore/FSPageTemplate.py", line 237, in _exec
result = self.pt_render(extra_context=bound_names)
File "/Users/mikko/code/buildout-cache/eggs/Products.CMFCore-2.2.6-py2.7.egg/Products/CMFCore/FSPageTemplate.py", line 177, in pt_render
self, source, extra_context
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Products/PageTemplates/PageTemplate.py", line 79, in pt_render
showtal=showtal)
File "/Users/mikko/code/buildout-cache/eggs/zope.pagetemplate-3.5.2-py2.7.egg/zope/pagetemplate/pagetemplate.py", line 113, in pt_render
strictinsert=0, sourceAnnotations=sourceAnnotations)()
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 271, in __call__
self.interpret(self.program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 888, in do_useMacro
self.interpret(macro)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 533, in do_optTag_tal
self.do_optTag(stuff)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 518, in do_optTag
return self.no_tag(start, program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 513, in no_tag
self.interpret(program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 954, in do_defineSlot
self.interpret(block)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 533, in do_optTag_tal
self.do_optTag(stuff)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 518, in do_optTag
return self.no_tag(start, program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 513, in no_tag
self.interpret(program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 858, in do_defineMacro
self.interpret(macro)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 852, in do_condition
self.interpret(block)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 742, in do_insertStructure_tal
structure = self.engine.evaluateStructure(expr)
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Products/PageTemplates/Expressions.py", line 218, in evaluateStructure
text = super(ZopeContext, self).evaluateStructure(expr)
File "/Users/mikko/code/buildout-cache/eggs/zope.tales-3.5.2-py2.7.egg/zope/tales/tales.py", line 696, in evaluate
return expression(self)
- file:/Users/mikko/code/xxx-dev/src/xxx-packages/plonetheme.xxxexternal/plonetheme/xxxexternal/skins/plonetheme_xxxexternal_custom_templates/main_template.pt
- Line 83, Column 20
- Expression: <StringExpr u'plone.contentviews'>
- Names:
{'container': <PloneSite at /plone>,
'context': <RegistrationTool at /plone/portal_registration used for /plone/portal_memberdata/xxx_manager>,
'default': <object object at 0x10204e970>,
'here': <RegistrationTool at /plone/portal_registration used for /plone/portal_memberdata/xxx_manager>,
'loop': {},
'nothing': None,
'options': {'args': (<RegistrationTool at /plone/portal_registration used for /plone/portal_memberdata/xxx_manager>,
<HTTPRequest, URL=http://localhost:55001>)},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x107704c00>,
'request': <HTTPRequest, URL=http://localhost:55001>,
'root': <Application at >,
'template': <FSPageTemplate at /plone/mail_password_response used for /plone/portal_registration>,
'traverse_subpath': [],
'user': <PloneUser 'admin'>}
File "/Users/mikko/code/buildout-cache/eggs/zope.contentprovider-3.7.2-py2.7.egg/zope/contentprovider/tales.py", line 80, in __call__
return provider.render()
File "/Users/mikko/code/buildout-cache/eggs/plone.app.viewletmanager-2.0.2-py2.7.egg/plone/app/viewletmanager/manager.py", line 154, in render
return BaseOrderedViewletManager.render(self)
File "/Users/mikko/code/buildout-cache/eggs/plone.app.viewletmanager-2.0.2-py2.7.egg/plone/app/viewletmanager/manager.py", line 85, in render
return u'\n'.join([viewlet.render() for viewlet in self.viewlets])
File "/Users/mikko/code/buildout-cache/eggs/plone.app.layout-2.1.13-py2.7.egg/plone/app/layout/viewlets/common.py", line 48, in render
return self.index()
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Products/Five/browser/pagetemplatefile.py", line 125, in __call__
return self.im_func(im_self, *args, **kw)
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Products/Five/browser/pagetemplatefile.py", line 59, in __call__
sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0),
File "/Users/mikko/code/buildout-cache/eggs/zope.pagetemplate-3.5.2-py2.7.egg/zope/pagetemplate/pagetemplate.py", line 113, in pt_render
strictinsert=0, sourceAnnotations=sourceAnnotations)()
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 271, in __call__
self.interpret(self.program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 852, in do_condition
self.interpret(block)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 531, in do_optTag_tal
self.no_tag(stuff[-2], stuff[-1])
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 513, in no_tag
self.interpret(program)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 343, in interpret
handlers[opcode](self, args)
File "/Users/mikko/code/buildout-cache/eggs/zope.tal-3.5.2-py2.7.egg/zope/tal/talinterpreter.py", line 583, in do_setLocal_tal
self.engine.setLocal(name, self.engine.evaluateValue(expr))
File "/Users/mikko/code/buildout-cache/eggs/zope.tales-3.5.2-py2.7.egg/zope/tales/tales.py", line 696, in evaluate
return expression(self)
- /Users/mikko/code/buildout-cache/eggs/plone.app.layout-2.1.13-py2.7.egg/plone/app/layout/viewlets/contentviews.pt
- Line 6, Column 4
- Expression: <PathExpr standard:u'view/prepareObjectTabs'>
- Names:
{'args': (),
'container': <RegistrationTool at /plone/portal_registration used for /plone/portal_memberdata/xxx_manager>,
'context': <RegistrationTool at /plone/portal_registration used for /plone/portal_memberdata/xxx_manager>,
'default': <object object at 0x10204e970>,
'here': <RegistrationTool at /plone/portal_registration used for /plone/portal_memberdata/xxx_manager>,
'loop': {},
'nothing': None,
'options': {},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x107afe050>,
'request': <HTTPRequest, URL=http://localhost:55001>,
'root': <Application at >,
'template': <Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x105dfb810>,
'traverse_subpath': [],
'user': <PloneUser 'admin'>,
'view': <Products.Five.viewlet.metaconfigure.ContentViewsViewlet object at 0x10868c050>,
'views': <Products.Five.browser.pagetemplatefile.ViewMapper object at 0x107ff1f90>}
File "/Users/mikko/code/buildout-cache/eggs/zope.tales-3.5.2-py2.7.egg/zope/tales/expressions.py", line 217, in __call__
return self._eval(econtext)
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Products/PageTemplates/Expressions.py", line 155, in _eval
return render(ob, econtext.vars)
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/Products/PageTemplates/Expressions.py", line 117, in render
ob = ob()
File "/Users/mikko/code/buildout-cache/eggs/plone.memoize-1.1.1-py2.7.egg/plone/memoize/view.py", line 47, in memogetter
value = cache[key] = func(*args, **kwargs)
File "/Users/mikko/code/buildout-cache/eggs/plone.app.layout-2.1.13-py2.7.egg/plone/app/layout/viewlets/common.py", line 258, in prepareObjectTabs
request_url = self.request['ACTUAL_URL']
File "/Users/mikko/code/buildout-cache/eggs/Zope2-2.13.15-py2.7.egg/ZPublisher/HTTPRequest.py", line 1372, in __getitem__
raise KeyError, key
KeyError: 'ACTUAL_URL'