Commit aaa39279 authored by Romain Courteaud's avatar Romain Courteaud

Implement access token to ease computer creation.

Allow to query the web site without copy/pasting the user SSL certificates.
The query should be like:
curl -X POST -H "X-Access-Token: ACCESSTOKENVALUE" -d "title=COMPUTERTITLE" "https://slaposmaster.example.org/add-a-server/WebSection_registerNewComputer"

Access token is destroyed after usage.
The token validity is one day.
parent 8016bb1c
...@@ -51,6 +51,9 @@ ...@@ -51,6 +51,9 @@
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>promise_dict = {\n <value> <string>promise_dict = {\n
\'IExtractionPlugin\': [\n
\'ERP5 Access Token Extraction Plugin\',\n
],\n
\'IExtractionPlugin\': [\n \'IExtractionPlugin\': [\n
\'SlapOS Machine Authentication Plugin\',\n \'SlapOS Machine Authentication Plugin\',\n
],\n ],\n
......
277 278
\ No newline at end of file \ No newline at end of file
<local_roles_item>
<local_roles>
<role id='G-COMPANY'>
<item>Auditor</item>
<item>Author</item>
</role>
<role id='R-MEMBER'>
<item>Author</item>
</role>
<role id='zope'>
<item>Owner</item>
</role>
</local_roles>
</local_roles_item>
\ No newline at end of file
<type_roles>
<role id='Author; Auditor'>
<property id='title'>Group company</property>
<multi_property id='category'>group/company</multi_property>
<multi_property id='base_category'>group</multi_property>
</role>
<role id='Author'>
<property id='title'>Member</property>
<multi_property id='category'>role/member</multi_property>
<multi_property id='base_category'>role</multi_property>
</role>
</type_roles>
\ No newline at end of file
<type_roles>
<role id='Assignor'>
<property id='title'>Group company</property>
<multi_property id='category'>group/company</multi_property>
<multi_property id='base_category'>group</multi_property>
</role>
</type_roles>
\ No newline at end of file
...@@ -1982,3 +1982,22 @@ class TestRegularisationRequest(TestSlapOSGroupRoleSecurityMixin): ...@@ -1982,3 +1982,22 @@ class TestRegularisationRequest(TestSlapOSGroupRoleSecurityMixin):
self.assertRoles(product, 'R-MEMBER', ['Auditor']) self.assertRoles(product, 'R-MEMBER', ['Auditor'])
self.assertPermissionsOfRole(product, 'Auditor', self.assertPermissionsOfRole(product, 'Auditor',
['Access contents information', 'View']) ['Access contents information', 'View'])
class TestAccessTokenModule(TestSlapOSGroupRoleSecurityMixin):
def test(self):
module = self.portal.access_token_module
self.assertSecurityGroup(module,
['G-COMPANY', 'R-MEMBER', 'zope'], False)
self.assertRoles(module, 'G-COMPANY', ['Auditor', 'Author'])
self.assertRoles(module, 'R-MEMBER', ['Author'])
self.assertRoles(module, 'zope', ['Owner'])
class TestOneTimeRestrictedAccessToken(TestSlapOSGroupRoleSecurityMixin):
def test_GroupCompany(self):
product = self.portal.access_token_module.newContent(
portal_type='One Time Restricted Access Token')
product.updateLocalRolesOnSecurityGroups()
self.assertSecurityGroup(product,
['G-COMPANY', self.user_id], False)
self.assertRoles(product, 'G-COMPANY', ['Assignor'])
self.assertRoles(product, self.user_id, ['Owner'])
167 168
\ No newline at end of file \ No newline at end of file
access_token_module
account_module account_module
account_module/bank account_module/bank
account_module/capital account_module/capital
......
access_token_module
account_module account_module
account_module/bank account_module/bank
account_module/capital account_module/capital
......
Access Token Module
Account Account
Account Module Account Module
Accounting Period Accounting Period
...@@ -54,6 +55,7 @@ Meeting Module ...@@ -54,6 +55,7 @@ Meeting Module
Note Note
Notification Message Notification Message
Notification Message Module Notification Message Module
One Time Restricted Access Token
Open Sale Order Open Sale Order
Open Sale Order Module Open Sale Order Module
Organisation Organisation
......
Access Token Module
One Time Restricted Access Token
Account Account
Account Module Account Module
Accounting Period Accounting Period
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>import json\n
\n
portal = context.getPortalObject()\n
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n
\n
web_site = context.getWebSiteValue()\n
request_method = "POST"\n
request_url = "%s/%s" % (web_site.absolute_url(), "add-a-server/WebSection_registerNewComputer")\n
\n
access_token = portal.access_token_module.newContent(\n
portal_type="One Time Restricted Access Token",\n
agent_value=person,\n
url_string=request_url,\n
url_method="POST",\n
)\n
access_token.validate()\n
\n
request = context.REQUEST\n
response = request.RESPONSE\n
response.setHeader(\'Content-Type\', "application/json")\n
return json.dumps({\'access_token\': access_token.getId()})\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_generateAccessTokenFromJS</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
return """\n
<script>\n
"use strict";\n
(function ($) {\n
\n
var methods;\n
\n
methods = {\n
click: function () {\n
$(this).click(function() {\n
$(this).parent().parent()\n
.slapostoken("generateToken");\n
return false;\n
});\n
},\n
generateToken: function () {\n
$.ajax("./Base_generateAccessTokenFromJS", {\n
context: $(this),\n
success: function(data) {\n
$(this).attr("class", "alignr")\n
.text("New token: " + data.access_token);\n
}\n
})\n
},\n
};\n
\n
$.fn.slapostoken = function (method) {\n
var result;\n
if (methods.hasOwnProperty(method)) {\n
result = methods[method].apply(\n
this,\n
Array.prototype.slice.call(arguments, 1)\n
);\n
} else {\n
$.error(\'Method \' + method +\n
\' does not exist on jQuery.slapostoken\');\n
}\n
return result;\n
};\n
}(jQuery));\n
\n
$("#tokengenerationlink")\n
.slapostoken("click");\n
</script>\n
"""\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_getTokenGeneratorJS</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -52,13 +52,20 @@ ...@@ -52,13 +52,20 @@
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n <value> <string>portal = context.getPortalObject()\n
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n
request_kw = dict(computer_title=title)\n \n
person.requestComputer(**request_kw)\n request = context.REQUEST\n
computer = context.restrictedTraverse(context.REQUEST.get(\'computer\'))\n response = request.RESPONSE\n
computer.generateCertificate()\n \n
message = "Registering Computer"\n if person is None:\n
context.REQUEST.set("portal_status_message", message)\n response.setStatus(403)\n
return computer.Computer_viewConnectionInformationAsWeb()\n else:\n
request_kw = dict(computer_title=title)\n
person.requestComputer(**request_kw)\n
computer = context.restrictedTraverse(context.REQUEST.get(\'computer\'))\n
computer.generateCertificate()\n
message = "Registering Computer"\n
context.REQUEST.set("portal_status_message", message)\n
return computer.Computer_viewConnectionInformationAsWeb()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -90,6 +90,8 @@ ...@@ -90,6 +90,8 @@
<string>my_certificate_request_button</string> <string>my_certificate_request_button</string>
<string>my_certificate_revoke_button</string> <string>my_certificate_revoke_button</string>
<string>my_update_credential_button</string> <string>my_update_credential_button</string>
<string>my_token_generate_button</string>
<string>your_ad</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>css_class</string>
<string>default</string>
<string>extra</string>
<string>href</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_token_generate_button</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>href</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>css_class</string> </key>
<value> <string>nolabel validate alignr</string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string>Generate a security token</string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string>id="tokengenerationlink"</string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_hyperlink</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewWebFieldLibrary</string> </value>
</item>
<item>
<key> <string>href</string> </key>
<value> <string>./</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Generate a token</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -6,4 +6,5 @@ erp5_web ...@@ -6,4 +6,5 @@ erp5_web
erp5_rss_style erp5_rss_style
erp5_credential_oauth2 erp5_credential_oauth2
erp5_bearer_token erp5_bearer_token
erp5_access_token
slapos_pdm slapos_pdm
\ No newline at end of file
48 49
\ No newline at end of file \ No newline at end of file
...@@ -231,6 +231,7 @@ class testSlapOSMixin(ERP5TypeTestCase): ...@@ -231,6 +231,7 @@ class testSlapOSMixin(ERP5TypeTestCase):
'erp5_credential_oauth2', 'erp5_credential_oauth2',
'erp5_accounting_l10n_fr', 'erp5_accounting_l10n_fr',
'erp5_bearer_token', 'erp5_bearer_token',
'erp5_access_token',
'erp5_project', 'erp5_project',
'slapos_cache', 'slapos_cache',
'slapos_cloud', 'slapos_cloud',
......
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