Commit f99d671c authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_cloud&erp5: Migrate to ERP5Type_asSecurityGroupSet

  Include a custom ERP5Type_asSecurityGroupIdSet, since we need to handle
  the order of source_project + function (sort) a non-standard way.
parent 58bc5efb
"""
This script is used to convert a list of categories into an security
identifier (security ID). It is invoked by two classes in ERP5:
- ERP5Type.py to convert security definitions made of
multiple categories into security ID strings
- ERP5GroupManager.py to convert an assignment definition
into a single security ID string. It should be noted here
that ERP5GroupManager.py also tries to invoke ERP5Type_asSecurityGroupIdList
(DEPRECATED) in order associate a user to multiple security groups.
In this case ERP5Type_asSecurityGroupId is not invoked.
The script takes the following parameters:
category_order - list of base_categories we want to use to generate the group id
kw - keys should be base categories, values should be value
of corresponding relative urls (obtained by getBaseCategory())
Example call:
context.ERP5TypeSecurity_asGroupId(category_order=('site', 'group', 'function'),
site='france/lille', group='nexedi', function='accounting/accountant')
This will generate a string like 'LIL_NXD_ACT' where "LIL", "NXD" and "ACT" are
the codification of respecively "france/lille", "nexedi" and "accounting/accountant" categories
If the category points to a document portal type (ex. trade condition, project, etc.),
and if no codification property is defined for this type of object,
the security ID group is generated by considering the object reference or
the object ID.
ERP5Type_asSecurityGroupId can also return a list of users whenever a category points
to a Person instance. This is useful to implement user based local role assignments
instead of abstract security based local roles.
"""
portal = context.getPortalObject()
getCategoryValue = portal.portal_categories.getCategoryValue
# sort the category list lexicographically
# this prevents us to choose the exact order we want,
# but also prevents some human mistake to break everything by creating site_function instead of function_site
if category_order not in (None, ''):
category_order = list(category_order)
# Do not sort, otherwise, it is not possible to ensure source_section/function and destination/function generate the same local role
#category_order.sort()
else:
category_order = []
# Prepare a cartesian product
from Products.ERP5Type.Utils import cartesianProduct
list_of_list = []
user_list = []
for base_category in category_order:
# It is acceptable for a category not to be defined
try:
category_list = kw[base_category]
except KeyError:
continue
associative_list = []
if isinstance(category_list, str):
category_list = [category_list]
for category in category_list:
if category[-1] == '*':
category = category[:-1]
is_child_category = 1
else:
is_child_category = 0
category_path = '%s/%s' % (base_category, category)
category_object = getCategoryValue(category_path)
if category_object is None:
raise RuntimeError("Security definition error (category %r not found)" % (category_path,))
portal_type = category_object.getPortalType()
if portal_type in ['Person', 'Compute Node', 'Software Instance']:
# We define a person here
user_name = category_object.Person_getUserId()
if user_name is not None:
user_list.append(user_name)
else:
category_code = (category_object.getProperty('codification') or
category_object.getProperty('reference') or
category_object.getId())
if is_child_category:
category_code += '*'
associative_list.append(category_code)
# Prevent making a cartesian product with an empty set
if associative_list:
list_of_list.append(associative_list)
# Return a list of users if any was defined
if user_list:
return user_list
# Compute the cartesian product and return the codes
# return filter(lambda x: x, map(lambda x: '_'.join(x), cartesianProduct(list_of_list)))
return ['_'.join(x) for x in cartesianProduct(list_of_list) if x]
def handleSort(_category_dict):
# Ensure that destination_project + function and source_project + function
# generates the same Security ID. This workarround is required because
# the value already arrives at this point pre-sorted on various locations
# and it is not possible to change since it is widely used.
category_list = sorted(_category_dict.keys())
if category_list == ['function', 'source_project']:
return ['source_project', 'function']
# Enforce return list in case
return category_list
return context.portal_skins.erp5_core.ERP5Type_asSecurityGroupIdSet(
category_dict=category_dict, key_sort=handleSort)
......@@ -50,11 +50,11 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>category_order, **kw</string> </value>
<value> <string>category_dict, key_sort=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Type_asSecurityGroupId</string> </value>
<value> <string>ERP5Type_asSecurityGroupIdSet</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -63,7 +63,6 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template):
'slapos_cloud/ComputeNode_invalidateIfEmpty',
'slapos_cloud/AllocationSupplyCell_asPredicate',
'slapos_cloud/AllocationSupplyLine_asPredicate',
'slapos_cloud/ERP5Type_asSecurityGroupId',
'slapos_cloud/InstanceTree_getDefaultImageAbsoluteUrl',
'slapos_cloud/InstanceTree_getSoftwareProduct',
'slapos_cloud/InstanceTree_requestParameterChange',
......@@ -199,6 +198,7 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template):
'slapos_administration/z_get_uid_group_from_roles_and_users',
'slapos_administration/SoftwareInstance_renewCertificate',
'slapos_core/ERP5Type_getSecurityCategoryMapping',
'slapos_core/ERP5Type_asSecurityGroupIdSet',
'slapos_base/Login_getFastExpirationReferenceList',
'slapos_base/Login_isLoginBlocked',
'slapos_base/Login_isPasswordExpired',
......
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