diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.py b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.py similarity index 100% rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.py rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.py diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.xml b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.xml similarity index 96% rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.xml rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.xml index f6aa05a4b62ada596daf446b2a330df239f4bdee..ef6d82513f1f93024080546a26974ce18485ac86 100644 --- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.xml +++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.xml @@ -54,7 +54,7 @@ </item> <item> <key> <string>id</string> </key> - <value> <string>AccessToken_getExternalLogin</string> </value> + <value> <string>AccessToken_getUserValue</string> </value> </item> </dictionary> </pickle> diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.py b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.py similarity index 92% rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.py rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.py index e15560b82e981fc25da6972873cca818e2f2bdc0..1082749445339af562cf8752a5f3dc82d1f7ccd1 100644 --- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.py +++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.py @@ -14,7 +14,7 @@ if access_token_document.getValidationState() == 'validated': agent_document = access_token_document.getAgentValue() if agent_document is not None: - result = agent_document.Person_getUserId() + result = agent_document comment = "Token usage accepted" access_token_document.invalidate(comment=comment) diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.xml b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.xml similarity index 96% rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.xml rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.xml index 75149e9cf552843f4246527890cd0de07f4f4840..e27079e582e40eb4f11b0ae46058833cc3d68a55 100644 --- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.xml +++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.xml @@ -54,7 +54,7 @@ </item> <item> <key> <string>id</string> </key> - <value> <string>OneTimeRestrictedAccessToken_getExternalLogin</string> </value> + <value> <string>OneTimeRestrictedAccessToken_getUserValue</string> </value> </item> </dictionary> </pickle> diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.py b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.py similarity index 93% rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.py rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.py index 24685e0cc1bfe6e40bb3fe31b05bb2e1e1bd23db..358798ce3f4184d291bf74068709091bbe66f966 100644 --- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.py +++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.py @@ -19,9 +19,9 @@ if access_token_document.getValidationState() == 'validated': # use hmac.compare_digest and not string comparison to avoid timing attacks if not hmac.compare_digest(access_token_document.getReference(), reference): return None - + agent_document = access_token_document.getAgentValue() if agent_document is not None: - result = agent_document.Person_getUserId() + result = agent_document return result diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.xml b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.xml similarity index 96% rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.xml rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.xml index a126952abf365ac81694e35dc1e37478a533b081..e8c7c5a41cbaf6d7b858f966e4cf543114c5c6be 100644 --- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.xml +++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.xml @@ -54,7 +54,7 @@ </item> <item> <key> <string>id</string> </key> - <value> <string>RestrictedAccessToken_getExternalLogin</string> </value> + <value> <string>RestrictedAccessToken_getUserValue</string> </value> </item> </dictionary> </pickle> diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.py new file mode 100644 index 0000000000000000000000000000000000000000..31c1991cd27930a251d8272e31c92fd282081a76 --- /dev/null +++ b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2002-2019 Nexedi SA and Contributors. All Rights Reserved. +# Tristan Cavelier <tristan.cavelier@nexedi.com> +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from ZPublisher.HTTPRequest import HTTPRequest +from ZPublisher.HTTPResponse import HTTPResponse +from DateTime import DateTime +import base64 +import StringIO +from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase +from Products.ERP5Security.ERP5DumbHTTPExtractionPlugin import ERP5DumbHTTPExtractionPlugin + + +class AccessTokenTestCase(ERP5TypeTestCase): + def getBusinessTemplateList(self): + return ('erp5_base', + 'erp5_access_token') + + def _createPerson(self, new_id, password=None): + """Creates a person in person module, and returns the object, after + indexing is done. """ + person_module = self.getPersonModule() + person = person_module.newContent(portal_type='Person', + reference='TESTP-' + new_id) + if password: + person.setPassword(password) + person.newContent(portal_type = 'Assignment').open() + self.tic() + return person + + +class TestERP5AccessTokenSkins(AccessTokenTestCase): + test_token_extraction_id = 'test_erp5_access_token_extraction' + + def generateNewId(self): + return str(self.portal.portal_ids.generateNewId( + id_group=('erp5_access_token_test_id'))) + + def afterSetUp(self): + """ + This is ran before anything, used to set the environment + """ + self.new_id = self.generateNewId() + self._setupAccessTokenExtraction() + self.tic() + + def _setupAccessTokenExtraction(self): + pas = self.portal.acl_users + access_extraction_list = [q for q in pas.objectValues() \ + if q.meta_type == 'ERP5 Access Token Extraction Plugin'] + if len(access_extraction_list) == 0: + dispacher = pas.manage_addProduct['ERP5Security'] + dispacher.addERP5AccessTokenExtractionPlugin(self.test_token_extraction_id) + getattr(pas, self.test_token_extraction_id).manage_activateInterfaces( + ('IExtractionPlugin', 'IAuthenticationPlugin')) + elif len(access_extraction_list) == 1: + self.test_token_extraction_id = access_extraction_list[0].getId() + elif len(access_extraction_list) > 1: + raise ValueError + self.commit() + + def _getTokenCredential(self, request): + """Authenticate the request and return (user_id, login) or None if not authorized.""" + plugin = getattr(self.portal.acl_users, self.test_token_extraction_id) + return plugin.authenticateCredentials(plugin.extractCredentials(request)) + + def _createRestrictedAccessToken(self, new_id, person, method, url_string): + access_token = self.portal.access_token_module.newContent( + portal_type="Restricted Access Token", + url_string=url_string, + url_method=method, + ) + if person: + access_token.edit(agent_value=person) + return access_token + + def _createOneTimeRestrictedAccessToken(self, new_id, person, method, url_string): + access_token = self.portal.access_token_module.newContent( + portal_type="One Time Restricted Access Token", + url_string=url_string, + url_method=method, + ) + if person: + access_token.edit(agent_value=person) + return access_token + + def test_working_token(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + access_token.validate() + self.tic() + + self.portal.REQUEST.form["access_token"] = access_token.getId() + self.portal.REQUEST["REQUEST_METHOD"] = access_method + self.portal.REQUEST["ACTUAL_URL"] = access_url + self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() + + result = self._getTokenCredential(self.portal.REQUEST) + self.assertTrue(result) + user_id, login = result + self.assertEqual(user_id, person.Person_getUserId()) + # tokens have a login value, for auditing purposes + self.assertEqual(access_token.getRelativeUrl(), login) + + def test_bad_token(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + access_token.validate() + self.tic() + + self.portal.REQUEST.form["access_token"] = "XYSYDT-YDTYSD" + self.portal.REQUEST["REQUEST_METHOD"] = access_method + self.portal.REQUEST["ACTUAL_URL"] = access_url + self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() + + result = self._getTokenCredential(self.portal.REQUEST) + self.assertFalse(result) + + def test_RestrictedAccessToken_getUserValue(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + access_token.validate() + self.tic() + + self.portal.REQUEST["REQUEST_METHOD"] = access_method + self.portal.REQUEST["ACTUAL_URL"] = access_url + self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() + + result = access_token.RestrictedAccessToken_getUserValue() + + self.assertEqual(result, person) + self.assertEqual(access_token.getValidationState(), 'validated') + + def test_RestrictedAccessToken_getUserValue_access_token_secret(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + access_token.validate() + self.tic() + + self.portal.REQUEST["REQUEST_METHOD"] = access_method + self.portal.REQUEST["ACTUAL_URL"] = access_url + + result = access_token.RestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + self.portal.REQUEST.form["access_token_secret"] = "XYXYXYXY" + self.assertEqual(result, None) + + self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() + + result = access_token.RestrictedAccessToken_getUserValue() + + self.assertEqual(result, person) + self.assertEqual(access_token.getValidationState(), 'validated') + + def test_RestrictedAccessToken_getUserValue_no_agent(self): + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createRestrictedAccessToken(self.new_id, + None, + access_method, + access_url) + access_token.validate() + self.tic() + + self.portal.REQUEST["REQUEST_METHOD"] = access_method + self.portal.REQUEST["ACTUAL_URL"] = access_url + self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() + + result = access_token.RestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + def test_RestrictedAccessToken_getUserValue_wrong_values(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + self.tic() + result = access_token.RestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + access_token.validate() + self.tic() + + self.portal.REQUEST["REQUEST_METHOD"] = "POST" + self.portal.REQUEST["ACTUAL_URL"] = access_url + self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() + + result = access_token.RestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar" + + result = access_token.RestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + access_token.invalidate() + self.tic() + + result = access_token.RestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + + def test_OneTimeRestrictedAccessToken_getUserValue(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "GET" + access_token = self._createOneTimeRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + access_token.validate() + self.tic() + + self.portal.REQUEST["REQUEST_METHOD"] = access_method + self.portal.REQUEST["ACTUAL_URL"] = access_url + + result = access_token.OneTimeRestrictedAccessToken_getUserValue() + + self.assertEqual(result, person) + self.assertEqual(access_token.getValidationState(), 'invalidated') + + def test_OneTimeRestrictedAccessToken_getUserValue_wrong_values(self): + person = self._createPerson(self.new_id) + access_url = "http://exemple.com/foo" + access_method = "POST" + access_token = self._createOneTimeRestrictedAccessToken(self.new_id, + person, + access_method, + access_url) + self.tic() + result = access_token.OneTimeRestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + access_token.validate() + self.tic() + + self.portal.REQUEST["REQUEST_METHOD"] = "GET" + self.portal.REQUEST["ACTUAL_URL"] = access_url + + result = access_token.OneTimeRestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar" + + result = access_token.OneTimeRestrictedAccessToken_getUserValue() + self.assertEqual(result, None) + + +class TestERP5AccessTokenAlarm(AccessTokenTestCase): + + def test_alarm_old_validated_restricted_access_token(self): + access_token = self.portal.access_token_module.newContent( + portal_type="One Time Restricted Access Token", + ) + access_token.workflow_history['edit_workflow'] = [{ + 'comment':'Fake history', + 'error_message': '', + 'actor': 'ERP5TypeTestCase', + 'state': 'current', + 'time': DateTime('2012/11/15 11:11'), + 'action': 'foo_action' + }] + self.portal.portal_workflow._jumpToStateFor(access_token, 'validated') + self.tic() + + self.portal.portal_alarms.\ + erp5_garbage_collect_one_time_restricted_access_token.activeSense() + self.tic() + + self.assertEqual('invalidated', access_token.getValidationState()) + self.assertEqual( + 'Unused for 1 day.', + access_token.workflow_history['validation_workflow'][-1]['comment']) + + def test_alarm_recent_validated_restricted_access_token(self): + access_token = self.portal.access_token_module.newContent( + portal_type="One Time Restricted Access Token", + ) + self.portal.portal_workflow._jumpToStateFor(access_token, 'validated') + self.tic() + + self.portal.portal_alarms.\ + erp5_garbage_collect_one_time_restricted_access_token.activeSense() + self.tic() + + self.assertEqual('validated', access_token.getValidationState()) + + def test_alarm_old_non_validated_restricted_access_token(self): + access_token = self.portal.access_token_module.newContent( + portal_type="One Time Restricted Access Token", + ) + access_token.workflow_history['edit_workflow'] = [{ + 'comment':'Fake history', + 'error_message': '', + 'actor': 'ERP5TypeTestCase', + 'state': 'current', + 'time': DateTime('2012/11/15 11:11'), + 'action': 'foo_action' + }] + self.tic() + + self.portal.portal_alarms.\ + erp5_garbage_collect_one_time_restricted_access_token.activeSense() + self.tic() + + self.assertEqual('draft', access_token.getValidationState()) + + +class TestERP5DumbHTTPExtractionPlugin(AccessTokenTestCase): + + test_id = 'test_erp5_dumb_http_extraction' + + def generateNewId(self): + return str(self.portal.portal_ids.generateNewId( + id_group=('erp5_dumb_http_test_id'))) + + def afterSetUp(self): + """ + This is ran before anything, used to set the environment + """ + self.new_id = self.generateNewId() + self._setupDumbHTTPExtraction() + self.tic() + + def do_fake_request(self, request_method, headers=None): + if headers is None: + headers = {} + __version__ = "0.1" + env={} + env['SERVER_NAME']='bobo.server' + env['SERVER_PORT']='80' + env['REQUEST_METHOD']=request_method + env['REMOTE_ADDR']='204.183.226.81 ' + env['REMOTE_HOST']='bobo.remote.host' + env['HTTP_USER_AGENT']='Bobo/%s' % __version__ + env['HTTP_HOST']='127.0.0.1' + env['SERVER_SOFTWARE']='Bobo/%s' % __version__ + env['SERVER_PROTOCOL']='HTTP/1.0 ' + env['HTTP_ACCEPT']='image/gif, image/x-xbitmap, image/jpeg, */* ' + env['SERVER_HOSTNAME']='bobo.server.host' + env['GATEWAY_INTERFACE']='CGI/1.1 ' + env['SCRIPT_NAME']='Main' + env.update(headers) + return HTTPRequest(StringIO.StringIO(), env, HTTPResponse()) + + def _setupDumbHTTPExtraction(self): + pas = self.portal.acl_users + access_extraction_list = [q for q in pas.objectValues() \ + if q.meta_type == 'ERP5 Dumb HTTP Extraction Plugin'] + if len(access_extraction_list) == 0: + dispacher = pas.manage_addProduct['ERP5Security'] + dispacher.addERP5DumbHTTPExtractionPlugin(self.test_id) + getattr(pas, self.test_id).manage_activateInterfaces( + ('IExtractionPlugin',)) + elif len(access_extraction_list) == 1: + self.test_id = access_extraction_list[0].getId() + elif len(access_extraction_list) > 1: + raise ValueError + self.commit() + + def test_working_authentication(self): + self._createPerson(self.new_id, "test") + request = self.do_fake_request("GET", {"HTTP_AUTHORIZATION": "Basic " + base64.b64encode("%s:test" % self.new_id)}) + ret = ERP5DumbHTTPExtractionPlugin("default_extraction").extractCredentials(request) + self.assertEqual(ret, {'login': self.new_id, 'password': 'test', 'remote_host': 'bobo.remote.host', 'remote_address': '204.183.226.81 '}) diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.xml b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.xml similarity index 95% rename from bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.xml rename to bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.xml index ee8e0bbb804a770d2bef50290137fa0deababa8c..1e74dc9a62a0321337f5861a5b9929482973fbd7 100644 --- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.xml +++ b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.xml @@ -14,7 +14,7 @@ </item> <item> <key> <string>default_reference</string> </key> - <value> <string>testERP5AccessTokenSkins</string> </value> + <value> <string>testERP5AccessToken</string> </value> </item> <item> <key> <string>description</string> </key> @@ -24,7 +24,7 @@ </item> <item> <key> <string>id</string> </key> - <value> <string>test.erp5.testERP5AccessTokenSkins</string> </value> + <value> <string>test.erp5.testERP5AccessToken</string> </value> </item> <item> <key> <string>portal_type</string> </key> diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.py deleted file mode 100644 index 76fadf3070360143164b64fb6a3c8fd4f5464b0f..0000000000000000000000000000000000000000 --- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2002-2013 Nexedi SA and Contributors. All Rights Reserved. -from DateTime import DateTime -from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase - -class TestERP5AccessTokenAlarm(ERP5TypeTestCase): - - def getBusinessTemplateList(self): - return ('erp5_base', - 'erp5_access_token') - - def test_alarm_old_validated_restricted_access_token(self): - access_token = self.portal.access_token_module.newContent( - portal_type="One Time Restricted Access Token", - ) - access_token.workflow_history['edit_workflow'] = [{ - 'comment':'Fake history', - 'error_message': '', - 'actor': 'ERP5TypeTestCase', - 'state': 'current', - 'time': DateTime('2012/11/15 11:11'), - 'action': 'foo_action' - }] - self.portal.portal_workflow._jumpToStateFor(access_token, 'validated') - self.tic() - - self.portal.portal_alarms.\ - erp5_garbage_collect_one_time_restricted_access_token.activeSense() - self.tic() - - self.assertEqual('invalidated', access_token.getValidationState()) - self.assertEqual( - 'Unused for 1 day.', - access_token.workflow_history['validation_workflow'][-1]['comment']) - - def test_alarm_recent_validated_restricted_access_token(self): - access_token = self.portal.access_token_module.newContent( - portal_type="One Time Restricted Access Token", - ) - self.portal.portal_workflow._jumpToStateFor(access_token, 'validated') - self.tic() - - self.portal.portal_alarms.\ - erp5_garbage_collect_one_time_restricted_access_token.activeSense() - self.tic() - - self.assertEqual('validated', access_token.getValidationState()) - - def test_alarm_old_non_validated_restricted_access_token(self): - access_token = self.portal.access_token_module.newContent( - portal_type="One Time Restricted Access Token", - ) - access_token.workflow_history['edit_workflow'] = [{ - 'comment':'Fake history', - 'error_message': '', - 'actor': 'ERP5TypeTestCase', - 'state': 'current', - 'time': DateTime('2012/11/15 11:11'), - 'action': 'foo_action' - }] - self.tic() - - self.portal.portal_alarms.\ - erp5_garbage_collect_one_time_restricted_access_token.activeSense() - self.tic() - - self.assertEqual('draft', access_token.getValidationState()) diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.xml b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.xml deleted file mode 100644 index a961f71a54aa899609299b8def8f95bbdd95bf5a..0000000000000000000000000000000000000000 --- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?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>testERP5AccessTokenAlarm</string> </value> - </item> - <item> - <key> <string>description</string> </key> - <value> - <none/> - </value> - </item> - <item> - <key> <string>id</string> </key> - <value> <string>test.erp5.testERP5AccessTokenAlarm</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> diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.py deleted file mode 100644 index 6608f6033bc7bef032a0f16e30d35a35816c3d22..0000000000000000000000000000000000000000 --- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.py +++ /dev/null @@ -1,256 +0,0 @@ -# Copyright (c) 2002-2013 Nexedi SA and Contributors. All Rights Reserved. - -from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase -import transaction - -class TestERP5AccessTokenSkins(ERP5TypeTestCase): - - test_token_extraction_id = 'test_erp5_access_token_extraction' - - def getBusinessTemplateList(self): - return ('erp5_base', - 'erp5_access_token') - - def generateNewId(self): - return str(self.portal.portal_ids.generateNewId( - id_group=('erp5_access_token_test_id'))) - - def afterSetUp(self): - """ - This is ran before anything, used to set the environment - """ - self.portal = self.getPortalObject() - self.new_id = self.generateNewId() - self._setupAccessTokenExtraction() - transaction.commit() - self.tic() - - def _setupAccessTokenExtraction(self): - pas = self.portal.acl_users - access_extraction_list = [q for q in pas.objectValues() \ - if q.meta_type == 'ERP5 Access Token Extraction Plugin'] - if len(access_extraction_list) == 0: - dispacher = pas.manage_addProduct['ERP5Security'] - dispacher.addERP5AccessTokenExtractionPlugin(self.test_token_extraction_id) - getattr(pas, self.test_token_extraction_id).manage_activateInterfaces( - ('IExtractionPlugin',)) - elif len(access_extraction_list) == 1: - self.test_token_extraction_id = access_extraction_list[0].getId() - elif len(access_extraction_list) > 1: - raise ValueError - transaction.commit() - - def _createPerson(self, new_id): - """Creates a person in person module, and returns the object, after - indexing is done. """ - person_module = self.getPersonModule() - person = person_module.newContent(portal_type='Person', - user_id='TESTP-' + new_id) - person.newContent(portal_type = 'Assignment').open() - transaction.commit() - return person - - def _getTokenCredential(self, request): - plugin = getattr(self.portal.acl_users, self.test_token_extraction_id) - return plugin.extractCredentials(request) - - def _createRestrictedAccessToken(self, new_id, person, method, url_string): - access_token = self.portal.access_token_module.newContent( - portal_type="Restricted Access Token", - url_string=url_string, - url_method=method, - ) - if person: - access_token.edit(agent_value=person) - return access_token - - def _createOneTimeRestrictedAccessToken(self, new_id, person, method, url_string): - access_token = self.portal.access_token_module.newContent( - portal_type="One Time Restricted Access Token", - url_string=url_string, - url_method=method, - ) - if person: - access_token.edit(agent_value=person) - return access_token - - def test_working_token(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - access_token.validate() - self.tic() - - self.portal.REQUEST.form["access_token"] = access_token.getId() - self.portal.REQUEST["REQUEST_METHOD"] = access_method - self.portal.REQUEST["ACTUAL_URL"] = access_url - self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() - - result = self._getTokenCredential(self.portal.REQUEST) - self.assertEqual(result.get('external_login'), person.Person_getUserId()) - - def test_bad_token(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - access_token.validate() - self.tic() - - self.portal.REQUEST.form["access_token"] = "XYSYDT-YDTYSD" - self.portal.REQUEST["REQUEST_METHOD"] = access_method - self.portal.REQUEST["ACTUAL_URL"] = access_url - self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() - - result = self._getTokenCredential(self.portal.REQUEST) - self.assertEqual(result, {}) - - def test_RestrictedAccessToken_getExternalLogin(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - access_token.validate() - self.tic() - - self.portal.REQUEST["REQUEST_METHOD"] = access_method - self.portal.REQUEST["ACTUAL_URL"] = access_url - self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() - - result = access_token.RestrictedAccessToken_getExternalLogin() - - self.assertEqual(result, person.Person_getUserId()) - self.assertEqual(access_token.getValidationState(), 'validated') - - def test_RestrictedAccessToken_getExternalLogin_access_token_secret(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - access_token.validate() - self.tic() - - self.portal.REQUEST["REQUEST_METHOD"] = access_method - self.portal.REQUEST["ACTUAL_URL"] = access_url - - result = access_token.RestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - self.portal.REQUEST.form["access_token_secret"] = "XYXYXYXY" - self.assertEqual(result, None) - - self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() - - result = access_token.RestrictedAccessToken_getExternalLogin() - - self.assertEqual(result, person.Person_getUserId()) - self.assertEqual(access_token.getValidationState(), 'validated') - - def test_RestrictedAccessToken_getExternalLogin_no_agent(self): - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createRestrictedAccessToken(self.new_id, - None, - access_method, - access_url) - access_token.validate() - self.tic() - - self.portal.REQUEST["REQUEST_METHOD"] = access_method - self.portal.REQUEST["ACTUAL_URL"] = access_url - self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() - - result = access_token.RestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - def test_RestrictedAccessToken_getExternalLogin_wrong_values(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - self.tic() - result = access_token.RestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - access_token.validate() - self.tic() - - self.portal.REQUEST["REQUEST_METHOD"] = "POST" - self.portal.REQUEST["ACTUAL_URL"] = access_url - self.portal.REQUEST.form["access_token_secret"] = access_token.getReference() - - result = access_token.RestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar" - - result = access_token.RestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - access_token.invalidate() - self.tic() - - result = access_token.RestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - - def test_OneTimeRestrictedAccessToken_getExternalLogin(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "GET" - access_token = self._createOneTimeRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - access_token.validate() - self.tic() - - self.portal.REQUEST["REQUEST_METHOD"] = access_method - self.portal.REQUEST["ACTUAL_URL"] = access_url - - result = access_token.OneTimeRestrictedAccessToken_getExternalLogin() - - self.assertEqual(result, person.Person_getUserId()) - self.assertEqual(access_token.getValidationState(), 'invalidated') - - def test_OneTimeRestrictedAccessToken_getExternalLogin_wrong_values(self): - person = self.person = self._createPerson(self.new_id) - access_url = "http://exemple.com/foo" - access_method = "POST" - access_token = self._createOneTimeRestrictedAccessToken(self.new_id, - person, - access_method, - access_url) - self.tic() - result = access_token.OneTimeRestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - access_token.validate() - self.tic() - - self.portal.REQUEST["REQUEST_METHOD"] = "GET" - self.portal.REQUEST["ACTUAL_URL"] = access_url - - result = access_token.OneTimeRestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) - - self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar" - - result = access_token.OneTimeRestrictedAccessToken_getExternalLogin() - self.assertEqual(result, None) diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.py deleted file mode 100644 index bd2d3fb3a65d4c554ef07625f517083a2da22c43..0000000000000000000000000000000000000000 --- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2015 Nexedi SA and Contributors. All Rights Reserved. -# Tristan Cavelier <tristan.cavelier@nexedi.com> -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsability of assessing all potential -# consequences resulting from its eventual inadequacies and bugs -# End users who are looking for a ready-to-use solution with commercial -# garantees and support are strongly adviced to contract a Free Software -# Service Company -# -# This program is Free Software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -############################################################################## - -from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase -from ZPublisher.HTTPRequest import HTTPRequest -from ZPublisher.HTTPResponse import HTTPResponse -from Products.ERP5Security.ERP5DumbHTTPExtractionPlugin import ERP5DumbHTTPExtractionPlugin -import base64 -import transaction -import StringIO - -class TestERP5DumbHTTPExtractionPlugin(ERP5TypeTestCase): - - test_id = 'test_erp5_dumb_http_extraction' - - def getBusinessTemplateList(self): - return ('erp5_base',) - - def generateNewId(self): - return str(self.portal.portal_ids.generateNewId( - id_group=('erp5_dumb_http_test_id'))) - - def afterSetUp(self): - """ - This is ran before anything, used to set the environment - """ - self.portal = self.getPortalObject() - self.new_id = self.generateNewId() - self._setupDumbHTTPExtraction() - transaction.commit() - self.tic() - - def do_fake_request(self, request_method, headers=None): - if headers is None: - headers = {} - __version__ = "0.1" - env={} - env['SERVER_NAME']='bobo.server' - env['SERVER_PORT']='80' - env['REQUEST_METHOD']=request_method - env['REMOTE_ADDR']='204.183.226.81 ' - env['REMOTE_HOST']='bobo.remote.host' - env['HTTP_USER_AGENT']='Bobo/%s' % __version__ - env['HTTP_HOST']='127.0.0.1' - env['SERVER_SOFTWARE']='Bobo/%s' % __version__ - env['SERVER_PROTOCOL']='HTTP/1.0 ' - env['HTTP_ACCEPT']='image/gif, image/x-xbitmap, image/jpeg, */* ' - env['SERVER_HOSTNAME']='bobo.server.host' - env['GATEWAY_INTERFACE']='CGI/1.1 ' - env['SCRIPT_NAME']='Main' - env.update(headers) - return HTTPRequest(StringIO.StringIO(), env, HTTPResponse()) - - def _setupDumbHTTPExtraction(self): - pas = self.portal.acl_users - access_extraction_list = [q for q in pas.objectValues() \ - if q.meta_type == 'ERP5 Dumb HTTP Extraction Plugin'] - if len(access_extraction_list) == 0: - dispacher = pas.manage_addProduct['ERP5Security'] - dispacher.addERP5DumbHTTPExtractionPlugin(self.test_id) - getattr(pas, self.test_id).manage_activateInterfaces( - ('IExtractionPlugin',)) - elif len(access_extraction_list) == 1: - self.test_id = access_extraction_list[0].getId() - elif len(access_extraction_list) > 1: - raise ValueError - transaction.commit() - - def _createPerson(self, new_id, password=None): - """Creates a person in person module, and returns the object, after - indexing is done. """ - person_module = self.getPersonModule() - person = person_module.newContent(portal_type='Person', - reference='TESTP-' + new_id) - if password: - person.setPassword(password) - person.newContent(portal_type = 'Assignment').open() - transaction.commit() - return person - - def test_working_authentication(self): - self._createPerson(self.new_id, "test") - request = self.do_fake_request("GET", {"HTTP_AUTHORIZATION": "Basic " + base64.b64encode("%s:test" % self.new_id)}) - ret = ERP5DumbHTTPExtractionPlugin("default_extraction").extractCredentials(request) - self.assertEqual(ret, {'login': self.new_id, 'password': 'test', 'remote_host': 'bobo.remote.host', 'remote_address': '204.183.226.81 '}) diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.xml b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.xml deleted file mode 100644 index 6c6f9f84fc517d6b3f26f8b4280fcd5abe954a28..0000000000000000000000000000000000000000 --- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?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>testERP5DumbHTTPExtractionPlugin</string> </value> - </item> - <item> - <key> <string>description</string> </key> - <value> - <none/> - </value> - </item> - <item> - <key> <string>id</string> </key> - <value> <string>test.erp5.testERP5DumbHTTPExtractionPlugin</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> diff --git a/bt5/erp5_access_token/bt/template_test_id_list b/bt5/erp5_access_token/bt/template_test_id_list index 3f19acd9e28344735d8c3fb584e1541505d6aa16..0279f3442a9ccea4b7fb1d546c6354926a5df1bc 100644 --- a/bt5/erp5_access_token/bt/template_test_id_list +++ b/bt5/erp5_access_token/bt/template_test_id_list @@ -1,3 +1 @@ -test.erp5.testERP5AccessTokenAlarm -test.erp5.testERP5AccessTokenSkins -test.erp5.testERP5DumbHTTPExtractionPlugin \ No newline at end of file +test.erp5.testERP5AccessToken \ No newline at end of file diff --git a/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py b/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py index da3279111b1c386629083f2915f4aa6ecb7d4c75..793a59efe38e526cf5855b961d6447852b1e7e01 100644 --- a/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py +++ b/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py @@ -59,35 +59,38 @@ class ERP5AccessTokenExtractionPlugin(BasePlugin): #ILoginPasswordHostExtractionPlugin# #################################### security.declarePrivate('extractCredentials') - @UnrestrictedMethod def extractCredentials(self, request): - """ Extract CookieHash credentials from the request header. """ + """ Extract credentials from the request header. """ creds = {} - # XXX Extract from HTTP Header, URL parameter are hardcoded. - # More flexible way would be to configure on the portal type level - token = request.getHeader("X-ACCESS-TOKEN", None) - if token is None: - token = request.form.get("access_token", None) - if token is not None: + # Extract token from HTTP Header + token = request.getHeader("X-ACCESS-TOKEN", request.form.get("access_token", None)) + if token: + creds['erp5_access_token_id'] = token + creds['remote_host'] = request.get('REMOTE_HOST', '') + try: + creds['remote_address'] = request.getClientAddr() + except AttributeError: + creds['remote_address'] = request.get('REMOTE_ADDR', '') + return creds + + ####################### + #IAuthenticationPlugin# + ####################### + security.declarePrivate('authenticateCredentials') + @UnrestrictedMethod + def authenticateCredentials(self, credentials): + """ Map credentials to a user ID. """ + if 'erp5_access_token_id' in credentials: + erp5_access_token_id = credentials['erp5_access_token_id'] token_document = self.getPortalObject().access_token_module.\ - _getOb(token, None) - # Access Token should be validated - # Check restricted access of URL - # Extract login information + _getOb(erp5_access_token_id, None) if token_document is not None: - external_login = None - method = token_document._getTypeBasedMethod('getExternalLogin') + method = token_document._getTypeBasedMethod('getUserValue') if method is not None: - external_login = method() - - if external_login is not None: - creds['external_login'] = external_login - creds['remote_host'] = request.get('REMOTE_HOST', '') - try: - creds['remote_address'] = request.getClientAddr() - except AttributeError: - creds['remote_address'] = request.get('REMOTE_ADDR', '') - return creds + user_value = method() + if user_value is not None: + return (user_value.getUserId(), token_document.getRelativeUrl()) + #Form for new plugin in ZMI manage_addERP5AccessTokenExtractionPluginForm = PageTemplateFile( @@ -109,6 +112,7 @@ def addERP5AccessTokenExtractionPlugin(dispatcher, id, title=None, REQUEST=None) #List implementation of class classImplements(ERP5AccessTokenExtractionPlugin, - plugins.ILoginPasswordHostExtractionPlugin - ) + plugins.ILoginPasswordHostExtractionPlugin, + plugins.IAuthenticationPlugin, + ) InitializeClass(ERP5AccessTokenExtractionPlugin)