Commit 726549e1 authored by Romain Courteaud's avatar Romain Courteaud

[erp5_hal_json_style] Check permission before accessing any document

parent 18e2f507
...@@ -1134,14 +1134,41 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1134,14 +1134,41 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
relative_url=None, restricted=None, list_method=None, relative_url=None, restricted=None, list_method=None,
default_param_json=None, form_relative_url=None, extra_param_json=None): default_param_json=None, form_relative_url=None, extra_param_json=None):
if relative_url: if (restricted == 1) and (portal.portal_membership.isAnonymousUser()):
try: login_relative_url = site_root.getLayoutProperty("configuration_login", default="")
traversed_document = site_root.restrictedTraverse(str(relative_url)) if (login_relative_url):
response.setHeader(
'WWW-Authenticate',
'X-Delegate uri="%s"' % (url_template_dict["login_template"] % {
"root_url": site_root.absolute_url(),
"login": login_relative_url
})
)
response.setStatus(401)
return ""
if (view is not None): if (view is not None):
view = str(view) view = str(view)
if relative_url:
is_site_root = False is_site_root = False
except: if traversed_document is None:
raise NotImplementedError(relative_url) traversed_document = site_root.restrictedTraverse(relative_url, None)
if (traversed_document is None):
response.setStatus(404)
return ""
elif traversed_document is None:
traversed_document = context
# Check if traversed_document is the site_root
if is_site_root is None:
is_site_root = (traversed_document.getPath() == site_root.getPath())
if is_portal is None:
is_portal = (traversed_document.getPath() == portal.getPath())
if mime_type != traversed_document.Base_handleAcceptHeader([mime_type]):
response.setStatus(406)
return ""
# extra_param_json holds parameters for search interpreted by getHateoas itself # extra_param_json holds parameters for search interpreted by getHateoas itself
# not by the list_method neither url_columns - only getHateoas # not by the list_method neither url_columns - only getHateoas
...@@ -1189,24 +1216,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1189,24 +1216,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
'status': statusLevelToString(portal_status_level) 'status': statusLevelToString(portal_status_level)
} }
if (restricted == 1) and (portal.portal_membership.isAnonymousUser()): if (mode == 'root') or (mode == 'traverse'):
login_relative_url = site_root.getLayoutProperty("configuration_login", default="")
if (login_relative_url):
response.setHeader(
'WWW-Authenticate',
'X-Delegate uri="%s"' % (url_template_dict["login_template"] % {
"root_url": site_root.absolute_url(),
"login": login_relative_url
})
)
response.setStatus(401)
return ""
elif mime_type != traversed_document.Base_handleAcceptHeader([mime_type]):
response.setStatus(406)
return ""
elif (mode == 'root') or (mode == 'traverse'):
## ##
# Render ERP Document with a `view` specified # Render ERP Document with a `view` specified
# `view` contains view's name and we extract view's URL (we suppose form ${object_url}/Form_view) # `view` contains view's name and we extract view's URL (we suppose form ${object_url}/Form_view)
...@@ -2108,22 +2118,8 @@ else: ...@@ -2108,22 +2118,8 @@ else:
context.Base_prepareCorsResponse(RESPONSE=response) context.Base_prepareCorsResponse(RESPONSE=response)
# Check if traversed_document is the site_root
if relative_url:
temp_traversed_document = site_root.restrictedTraverse(relative_url, None)
if (temp_traversed_document is None):
response.setStatus(404)
return ""
else:
temp_traversed_document = context
temp_is_site_root = (temp_traversed_document.getPath() == site_root.getPath())
temp_is_portal = (temp_traversed_document.getPath() == portal.getPath())
response.setHeader('Content-Type', mime_type) response.setHeader('Content-Type', mime_type)
hateoas = calculateHateoas(is_portal=temp_is_portal, is_site_root=temp_is_site_root, hateoas = calculateHateoas(relative_url=relative_url,
traversed_document=temp_traversed_document,
relative_url=relative_url,
REQUEST=REQUEST, response=response, view=view, mode=mode, REQUEST=REQUEST, response=response, view=view, mode=mode,
query=query, select_list=select_list, limit=limit, form=form, query=query, select_list=select_list, limit=limit, form=form,
restricted=restricted, list_method=list_method, restricted=restricted, list_method=list_method,
......
from erp5.component.test.testHalJsonStyle import ERP5HALJSONStyleSkinsMixin, simulate, changeSkin, do_fake_request
class TestHalRestricted(ERP5HALJSONStyleSkinsMixin):
@simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs',
'return "application/hal+json"')
@changeSkin('HalRestricted')
def test_mode_root(self):
fake_request = do_fake_request("GET")
self.logout()
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(REQUEST=fake_request)
self.assertEquals(fake_request.RESPONSE.status, 401)
self.assertEquals(fake_request.RESPONSE.getHeader('WWW-Authenticate'),
'X-Delegate uri="%s/connection/login_form{?came_from}"' % self.portal.web_site_module.hateoas.absolute_url()
)
@simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs',
'return "application/hal+json"')
@changeSkin('HalRestricted')
def test_mode_traverse(self):
document_relative_url = self._makeDocument().getRelativeUrl()
fake_request = do_fake_request("GET")
self.logout()
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(REQUEST=fake_request, mode="traverse", relative_url=document_relative_url)
self.assertEquals(fake_request.RESPONSE.status, 401)
self.assertEquals(fake_request.RESPONSE.getHeader('WWW-Authenticate'),
'X-Delegate uri="%s/connection/login_form{?came_from}"' % self.portal.web_site_module.hateoas.absolute_url()
)
@simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs',
'return "application/hal+json"')
@changeSkin('HalRestricted')
def test_mode_search(self):
fake_request = do_fake_request("GET")
self.logout()
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(REQUEST=fake_request, mode="search")
self.assertEquals(fake_request.RESPONSE.status, 401)
self.assertEquals(fake_request.RESPONSE.getHeader('WWW-Authenticate'),
'X-Delegate uri="%s/connection/login_form{?came_from}"' % self.portal.web_site_module.hateoas.absolute_url()
)
@simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs',
'return "application/hal+json"')
@changeSkin('HalRestricted')
def test_mode_worklist(self):
fake_request = do_fake_request("GET")
self.logout()
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(REQUEST=fake_request, mode="worklist")
self.assertEquals(fake_request.RESPONSE.status, 401)
self.assertEquals(fake_request.RESPONSE.getHeader('WWW-Authenticate'),
'X-Delegate uri="%s/connection/login_form{?came_from}"' % self.portal.web_site_module.hateoas.absolute_url()
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testHalRestrictedJsonStyle</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testHalRestrictedJsonStyle</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
test.erp5.testHalJsonStyle test.erp5.testHalJsonStyle
test.erp5.testHalRestrictedJsonStyle
\ No newline at end of file
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