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 @@
<item>
<key> <string>_body</string> </key>
<value> <string>promise_dict = {\n
\'IExtractionPlugin\': [\n
\'ERP5 Access Token Extraction Plugin\',\n
],\n
\'IExtractionPlugin\': [\n
\'SlapOS Machine Authentication Plugin\',\n
],\n
......
277
\ No newline at end of file
278
\ 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):
self.assertRoles(product, 'R-MEMBER', ['Auditor'])
self.assertPermissionsOfRole(product, 'Auditor',
['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
\ No newline at end of file
168
\ No newline at end of file
access_token_module
account_module
account_module/bank
account_module/capital
......
access_token_module
account_module
account_module/bank
account_module/capital
......
Access Token Module
Account
Account Module
Accounting Period
......@@ -54,6 +55,7 @@ Meeting Module
Note
Notification Message
Notification Message Module
One Time Restricted Access Token
Open Sale Order
Open Sale Order Module
Organisation
......
Access Token Module
One Time Restricted Access Token
Account
Account Module
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 @@
<key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\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
\n
request = context.REQUEST\n
response = request.RESPONSE\n
\n
if person is None:\n
response.setStatus(403)\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>
</item>
<item>
......
......@@ -90,6 +90,8 @@
<string>my_certificate_request_button</string>
<string>my_certificate_revoke_button</string>
<string>my_update_credential_button</string>
<string>my_token_generate_button</string>
<string>your_ad</string>
</list>
</value>
</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
erp5_rss_style
erp5_credential_oauth2
erp5_bearer_token
erp5_access_token
slapos_pdm
\ No newline at end of file
48
\ No newline at end of file
49
\ No newline at end of file
......@@ -231,6 +231,7 @@ class testSlapOSMixin(ERP5TypeTestCase):
'erp5_credential_oauth2',
'erp5_accounting_l10n_fr',
'erp5_bearer_token',
'erp5_access_token',
'erp5_project',
'slapos_cache',
'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