Commit 5272e987 authored by Ivan Tyagov's avatar Ivan Tyagov

Merge branch 'security_groups'

parents 90fb36be 88e9c81e
......@@ -31,8 +31,8 @@
DELETE FROM roles_and_users\n
<dtml-var sql_delimiter>\n
INSERT INTO roles_and_users (uid, allowedRolesAndUsers) VALUES\n
<dtml-in expr="getPortalObject().portal_catalog.getSQLCatalog().getRoleAndSecurityUidList()">\n
(<dtml-sqlvar sequence-item type="int">,<dtml-sqlvar sequence-key type="string">)<dtml-if sequence-end><dtml-else>,</dtml-if>\n
<dtml-in expr="role" expr="getPortalObject().portal_catalog.getSQLCatalog().getRoleAndSecurityUidList()">\n
(<dtml-sqlvar expr="role_item[0]" type="int">, <dtml-sqlvar expr="role_item[1]" type="string">, <dtml-sqlvar expr="role_item[2]" type="string">)<dtml-if sequence-end><dtml-else>,</dtml-if>\n
\n
</dtml-in>
......
<catalog_method>
<item key="sql_catalog_object_list" type="int">
<value>1</value>
</item>
</catalog_method>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>allow_simple_one_argument_traversal</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>optimised_roles_and_users</string> </value>
</item>
<item>
<key> <string>cache_time_</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>class_file_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>class_name_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_hook</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_catalog_roles_and_users_list</string> </value>
</item>
<item>
<key> <string>max_cache_</string> </key>
<value> <int>100</int> </value>
</item>
<item>
<key> <string>max_rows_</string> </key>
<value> <int>1000</int> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
<dtml-let row_list="[]">\n
<dtml-in prefix="loop" expr="_.range(_.len(optimised_roles_and_users))">\n
<dtml-in prefix="role" expr="optimised_roles_and_users[loop_item]">\n
<dtml-call expr="row_list.append([role_item[0], role_item[1], role_item[2]])">\n
</dtml-in>\n
</dtml-in>\n
<dtml-if expr="row_list">\n
INSERT INTO\n
roles_and_users(uid, local_roles_group_id, allowedRolesAndUsers)\n
VALUES\n
<dtml-in prefix="row" expr="row_list">\n
(<dtml-sqlvar expr="row_item[0]" type="string">, <dtml-sqlvar expr="row_item[1]" type="string">, <dtml-sqlvar expr="row_item[2]" type="string">)\n
<dtml-if sequence-end><dtml-else>,</dtml-if>\n
</dtml-in>\n
</dtml-if>\n
</dtml-let>\n
]]></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<catalog_method>
<item key="sql_clear_catalog" type="int">
<value>1</value>
</item>
</catalog_method>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_col</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>allow_simple_one_argument_traversal</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>arguments_src</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>cache_time_</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>class_file_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>class_name_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_hook</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_create_roles_and_users</string> </value>
</item>
<item>
<key> <string>max_cache_</string> </key>
<value> <int>100</int> </value>
</item>
<item>
<key> <string>max_rows_</string> </key>
<value> <int>1000</int> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string>CREATE TABLE roles_and_users (\n
uid INT UNSIGNED,\n
local_roles_group_id VARCHAR(255) default \'\',\n
allowedRolesAndUsers VARCHAR(255),\n
KEY `uid` (`uid`),\n
KEY `allowedRolesAndUsers` (`allowedRolesAndUsers`),\n
KEY `local_roles_group_id` (`local_roles_group_id`)\n
) ENGINE=InnoDB;\n
</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<catalog_method>
<item key="sql_search_security" type="int">
<value>1</value>
</item>
</catalog_method>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SQL" module="Products.ZSQLMethods.SQL"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>allow_simple_one_argument_traversal</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>security_roles_list</string> </value>
</item>
<item>
<key> <string>cache_time_</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>class_file_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>class_name_</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_hook</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>connection_id</string> </key>
<value> <string>erp5_sql_connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>z_search_security</string> </value>
</item>
<item>
<key> <string>max_cache_</string> </key>
<value> <int>100</int> </value>
</item>
<item>
<key> <string>max_rows_</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
SELECT\n
DISTINCT uid, local_roles_group_id\n
FROM \n
roles_and_users\n
WHERE \n
allowedRolesAndUsers \n
IN (<dtml-in security_roles_list><dtml-var sequence-item><dtml-if sequence-end><dtml-else>,</dtml-if></dtml-in>)\n
]]></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
2012-07-12 Ivan
* Initial import
\ No newline at end of file
This bt5 provides generic Z SQL methods that allows a site developer to split security uids into different catalog columns.
In order to use this optimization it's required to:
1. Make analyze which are most common uids
2. Place them in a new catalog column
3. Adjust respective z_catalog_object_list and z_create_catalog
Note: In order to use this technique a full catalog re-index is required.
\ No newline at end of file
3
\ No newline at end of file
erp5_mysql_innodb/z_catalog_roles_and_users_list
erp5_mysql_innodb/z_create_roles_and_users
erp5_mysql_innodb/z_search_security
\ No newline at end of file
1
\ No newline at end of file
erp5_security_uid_innodb_catalog
\ No newline at end of file
......@@ -545,7 +545,7 @@ class BaseTemplateItem(Implicit, Persistent):
classname = klass.__name__
attr_set = set(('_dav_writelocks', '_filepath', '_owner', 'last_id', 'uid',
'__ac_local_roles__'))
'__ac_local_roles__', '__ac_local_roles_group_id_dict__'))
if export:
if not keep_workflow_history:
attr_set.add('workflow_history')
......@@ -3047,11 +3047,12 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem):
k = k[5:]
elif k == 'role_name':
k, v = 'id', '; '.join(v)
elif k not in ('title', 'description'):
elif k not in ('title', 'description', 'categories'):
k = {'id': 'object_id', # for stable sort
'role_base_category': 'base_category',
'role_base_category_script_id': 'base_category_script',
'role_category': 'category'}.get(k)
'role_category': 'category',
'local_roles_group_id': 'local_roles_group_id'}.get(k)
if not k:
continue
type_role_dict[k] = v
......@@ -3074,7 +3075,7 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem):
xml_data += "\n <property id='%s'>%s</property>" % \
(property, prop_value)
# multi
for property in ('category', 'base_category'):
for property in ('categories', 'category', 'base_category'):
for prop_value in role.get(property, []):
if isinstance(prop_value, str):
prop_value = prop_value.decode('utf-8')
......@@ -3161,7 +3162,7 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem):
path = 'portal_types/%s' % roles_path.split('/', 1)[1]
try:
obj = p.unrestrictedTraverse(path)
setattr(obj, '_roles', [])
obj.manage_delObjects([x.id for x in obj.getRoleInformationList()])
except (NotFound, KeyError):
pass
......@@ -4360,6 +4361,12 @@ class CatalogLocalRoleKeyTemplateItem(CatalogUniqueKeyTemplateItemBase):
key_list_title = 'local_role_key_list'
key_title = 'LocalRole key'
class CatalogSecurityUidColumnTemplateItem(CatalogSearchKeyTemplateItem):
key_list_attr = 'sql_catalog_security_uid_columns'
key_list_title = 'security_uid_column_list'
key_title = 'Security Uid Columns'
class MessageTranslationTemplateItem(BaseTemplateItem):
def build(self, context, **kw):
......@@ -4532,13 +4539,27 @@ class LocalRolesTemplateItem(BaseTemplateItem):
obj = p.unrestrictedTraverse(path.split('/', 1)[1])
local_roles_dict = getattr(obj, '__ac_local_roles__',
{}) or {}
self._objects[path] = (local_roles_dict, )
local_roles_group_id_dict = getattr(
obj, '__ac_local_roles_group_id_dict__', {}) or {}
self._objects[path] = (local_roles_dict, local_roles_group_id_dict)
# Function to generate XML Code Manually
def generateXml(self, path=None):
local_roles_dict = self._objects[path][0]
# local roles
# With local roles groups id, self._object contains for each path a tuple
# containing the dict of local roles and the dict of local roles group ids.
# Before it was only containing the dict of local roles. This method is
# also used on installed business templates to show a diff during
# installation, so it might be called on old format objects.
if len(self._objects[path]) == 2:
# new format
local_roles_dict, local_roles_group_id_dict = self._objects[path]
else:
# old format, before local roles group id
local_roles_group_id_dict = dict()
local_roles_dict, = self._objects[path]
xml_data = '<local_roles_item>'
# local roles
xml_data += '\n <local_roles>'
for key in sorted(local_roles_dict):
xml_data += "\n <role id='%s'>" %(key,)
......@@ -4547,6 +4568,20 @@ class LocalRolesTemplateItem(BaseTemplateItem):
xml_data += "\n <item>%s</item>" %(item,)
xml_data += '\n </role>'
xml_data += '\n </local_roles>'
if local_roles_group_id_dict:
# local roles group id dict (not included by default to be stable with
# old bts)
xml_data += '\n <local_roles_group_id>'
for principal, local_roles_group_id_list in sorted(local_roles_group_id_dict.items()):
xml_data += "\n <principal id='%s'>" % escape(principal)
for local_roles_group_id in local_roles_group_id_list:
for item in local_roles_group_id:
xml_data += "\n <local_roles_group_id>%s</local_roles_group_id>" % \
escape(item)
xml_data += "\n </principal>"
xml_data += '\n </local_roles_group_id>'
xml_data += '\n</local_roles_item>'
if isinstance(xml_data, unicode):
xml_data = xml_data.encode('utf8')
......@@ -4571,7 +4606,15 @@ class LocalRolesTemplateItem(BaseTemplateItem):
id = role.get('id')
item_type_list = [item.text for item in role]
local_roles_dict[id] = item_type_list
self._objects['local_roles/%s' % (file_name[:-4],)] = (local_roles_dict, )
# local roles group id
local_roles_group_id_dict = {}
for principal in xml.findall('//principal'):
local_roles_group_id_dict[principal.get('id')] = set([tuple(
[group_id.text for group_id in
principal.findall('./local_roles_group_id')])])
self._objects['local_roles/%s' % (file_name[:-4],)] = (
local_roles_dict, local_roles_group_id_dict)
def install(self, context, trashbin, **kw):
update_dict = kw.get('object_to_update')
......@@ -4585,8 +4628,22 @@ class LocalRolesTemplateItem(BaseTemplateItem):
continue
path = roles_path.split('/')[1:]
obj = p.unrestrictedTraverse(path)
local_roles_dict = self._objects[roles_path][0]
# again we might be installing an business template in format before
# existance of local roles group id.
if len(self._objects[roles_path]) == 2:
local_roles_dict, local_roles_group_id_dict = self._objects[roles_path]
else:
local_roles_group_id_dict = dict()
local_roles_dict, = self._objects[roles_path]
setattr(obj, '__ac_local_roles__', local_roles_dict)
if local_roles_group_id_dict:
setattr(obj, '__ac_local_roles_group_id_dict__',
local_roles_group_id_dict)
# we try to have __ac_local_roles_group_id_dict__ set only if
# it is actually defining something else than default
elif getattr(aq_base(obj), '__ac_local_roles_group_id_dict__',
None) is not None:
delattr(obj, '__ac_local_roles_group_id_dict__')
obj.reindexObject()
def uninstall(self, context, object_path=None, **kw):
......@@ -4748,6 +4805,7 @@ Business Template is a set of definitions, such as skins, portal types and categ
'_catalog_scriptable_key_item',
'_catalog_role_key_item',
'_catalog_local_role_key_item',
'_catalog_security_uid_column_item',
]
def __init__(self, *args, **kw):
......@@ -4910,6 +4968,14 @@ Business Template is a set of definitions, such as skins, portal types and categ
self._catalog_local_role_key_item = \
CatalogLocalRoleKeyTemplateItem(
self.getTemplateCatalogLocalRoleKeyList())
try:
self._catalog_security_uid_column_item = \
CatalogSecurityUidColumnTemplateItem(
self.getTemplateCatalogSecurityUidColumnList())
except AttributeError:
# be backwards compatible with old zope instances which
# do not contain recent version of erp5_property_sheets
pass
security.declareProtected(Permissions.ManagePortal, 'build')
def build(self, no_action=0):
......@@ -5523,7 +5589,12 @@ Business Template is a set of definitions, such as skins, portal types and categ
(SimpleItem.SimpleItem,), {'__module__': module_id}))
for item_name in self._item_name_list:
getattr(self, item_name).importFile(bta)
item_object = getattr(self, item_name, None)
# this check is due to backwards compatability when there can be a
# difference between install erp5_property_sheets (esp. BusinessTemplate
# property sheet)
if item_object is not None:
item_object.importFile(bta)
# Remove temporary modules created above to allow import of real modules
# (during the installation).
......@@ -5631,6 +5702,7 @@ Business Template is a set of definitions, such as skins, portal types and categ
'CatalogScriptableKey' : '_catalog_scriptable_key_item',
'CatalogRoleKey' : '_catalog_role_key_item',
'CatalogLocalRoleKey' : '_catalog_local_role_key_item',
'CatalogSecurityUidColumn' : '_catalog_security_uid_column_item',
}
object_id = REQUEST.object_id
......@@ -5693,6 +5765,7 @@ Business Template is a set of definitions, such as skins, portal types and categ
'_catalog_scriptable_key_item',
'_catalog_role_key_item',
'_catalog_local_role_key_item',
'_catalog_security_uid_column_item',
'_portal_type_allowed_content_type_item',
'_portal_type_hidden_content_type_item',
'_portal_type_property_sheet_item',
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>local_role_group</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Local Role Group</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
......@@ -91,6 +91,7 @@
<string>my_template_catalog_topic_key_list</string>
<string>my_template_catalog_scriptable_key_list</string>
<string>my_template_catalog_local_role_key_list</string>
<string>my_template_catalog_security_uid_column_list</string>
</list>
</value>
</item>
......
......@@ -98,6 +98,7 @@
<string>my_title</string>
<string>my_role_name_list</string>
<string>my_condition</string>
<string>my_local_roles_group_id</string>
</list>
</value>
</item>
......
......@@ -16,6 +16,7 @@ destination_project
destination_section
destination_trade
elementary_type
local_role_group
mapping
order
origin
......
......@@ -14,8 +14,7 @@
</item>
<item>
<key> <string>arguments_src</string> </key>
<value> <string>security_uid\r\n
optimised_roles_and_users</string> </value>
<value> <string>optimised_roles_and_users</string> </value>
</item>
<item>
<key> <string>cache_time_</string> </key>
......@@ -56,16 +55,14 @@ optimised_roles_and_users</string> </value>
<value> <string encoding="cdata"><![CDATA[
<dtml-let row_list="[]">\n
<dtml-in prefix="loop" expr="_.range(_.len(security_uid))">\n
<dtml-if expr="optimised_roles_and_users[loop_item]">\n
<dtml-in prefix="loop" expr="_.range(_.len(optimised_roles_and_users))">\n
<dtml-in prefix="role" expr="optimised_roles_and_users[loop_item]">\n
<dtml-call expr="row_list.append([security_uid[loop_item], role_item])">\n
<dtml-call expr="row_list.append([role_item[0], role_item[2]])">\n
</dtml-in>\n
</dtml-if>\n
</dtml-in>\n
<dtml-if expr="row_list">\n
INSERT INTO\n
roles_and_users\n
roles_and_users(uid, allowedRolesAndUsers)\n
VALUES\n
<dtml-in prefix="row" expr="row_list">\n
(<dtml-sqlvar expr="row_item[0]" type="string">, <dtml-sqlvar expr="row_item[1]" type="string">)\n
......
......@@ -6,6 +6,12 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_col</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>allow_simple_one_argument_traversal</string> </key>
<value>
......
......@@ -52,10 +52,10 @@
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
SELECT \n
DISTINCT uid \n
SELECT\n
DISTINCT uid\n
FROM \n
roles_and_users \n
roles_and_users\n
WHERE \n
allowedRolesAndUsers \n
IN (<dtml-in security_roles_list><dtml-var sequence-item><dtml-if sequence-end><dtml-else>,</dtml-if></dtml-in>)\n
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/lines</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_catalog_security_uid_column_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: ()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>local_role_group_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -6597,6 +6597,90 @@ class TestBusinessTemplate(BusinessTemplateMixin):
new_bt5_obj.build()
template_tool.export(new_bt5_obj)
def test_local_roles_group_id(self):
"""Tests that roles definition defining local roles group ids are properly
exported and installed.
"""
# change security uid columns
sql_catalog = self.portal.portal_catalog.getSQLCatalog()
saved_sql_catalog_security_uid_columns = \
sql_catalog.sql_catalog_security_uid_columns
sql_catalog.sql_catalog_security_uid_columns = (
' | security_uid',
'Alternate | alternate_security_uid',
)
# add category
self.portal.portal_categories.local_role_group.newContent(
portal_type='Category',
reference = 'Alternate',
id = 'Alternate')
types_tool = self.portal.portal_types
object_type = types_tool.newContent('Geek Object', 'Base Type',
type_class='Person')
types_tool.newContent('Geek Module', 'Base Type',
type_class='Folder',
type_filter_content_type=1,
type_allowed_content_type_list=('Geek Object',), )
self.portal.newContent(portal_type='Geek Module', id='geek_module')
new_object = self.portal.geek_module.newContent(
portal_type='Geek Object', id='1')
# simulate role assignment
new_object.__ac_local_roles__ = dict(group=['Assignee'])
initial___ac_local_roles_group_id_dict__ = dict(Alternate=set([('group', 'Assignee')]))
new_object.__ac_local_roles_group_id_dict__ = initial___ac_local_roles_group_id_dict__
self.tic()
object_type.newContent(portal_type='Role Information',
local_role_group_value=self.portal.portal_categories.local_role_group.Alternate.getRelativeUrl(),
role_name_list=('Assignee', ))
bt = self.portal.portal_templates.newContent(
portal_type='Business Template',
title=self.id(),
template_local_roles_list=('geek_module/1',),
template_path_list=('geek_module/1',),
template_portal_type_role_list=('Geek Object',),)
self.tic()
bt.build()
self.tic()
export_dir = tempfile.mkdtemp()
try:
bt.export(path=export_dir, local=True)
self.tic()
new_bt = self.portal.portal_templates.download(
url='file://%s' % export_dir)
finally:
shutil.rmtree(export_dir)
# uninstall role information and paths
object_type.manage_delObjects([x.id for x in object_type.getRoleInformationList()])
self.portal.geek_module.manage_delObjects(['1'])
self.tic()
new_bt.install()
try:
role, = object_type.getRoleInformationList()
self.assertEquals(self.portal.portal_categories.local_role_group.Alternate,
role.getLocalRoleGroupValue())
path = self.portal.geek_module['1']
self.assertEquals([('group', ['Assignee'],)], [item for item in
path.__ac_local_roles__.items() if item[1] != ['Owner']])
self.assertEquals(initial___ac_local_roles_group_id_dict__,
path.__ac_local_roles_group_id_dict__)
finally:
# restore state
sql_catalog.sql_catalog_security_uid_columns = \
saved_sql_catalog_security_uid_columns
types_tool.manage_delObjects(['Geek Object', 'Geek Module'])
self.portal.manage_delObjects(['geek_module'])
self.tic()
def test_BusinessTemplateWithTest(self):
sequence_list = SequenceList()
sequence_string = '\
......
This diff is collapsed.
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Ivan Tyagov <ivan@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.
#
##############################################################################
import unittest
from Testing import ZopeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from AccessControl.SecurityManagement import newSecurityManager
class TestERP5CatalogSecurityUidOptimization(ERP5TypeTestCase):
"""
TestERP5CatalogSecurityUidOptimization tests security_uid optmization.
It is in a different test than TestERP5Catalog as it requires erp5_security_uid_innodb_catalog
bt5 to be installed in advance.
XXX: Inherit from TestERP5Catalog so we test default and security_uid optmization with same tests.
"""
business_template_list = ['erp5_security_uid_innodb_catalog',
'erp5_full_text_myisam_catalog','erp5_base']
def getBusinessTemplateList(self):
return self.business_template_list
def afterSetUp(self):
self.login()
portal = self.getPortal()
def test_local_roles_group_id_on_role_information(self):
"""Test usage of local_roles_group_id when searching catalog.
"""
sql_connection = self.getSQLConnection()
sql_catalog = self.portal.portal_catalog.getSQLCatalog()
# Add a catalog table (uid, alternate_security_uid)
sql_connection.manage_test(
"""DROP TABLE IF EXISTS alternate_roles_and_users""")
sql_connection.manage_test("""
CREATE TABLE alternate_roles_and_users (
`uid` BIGINT UNSIGNED NOT NULL,
`alternate_security_uid` INT UNSIGNED) """)
# make it a search table
current_sql_search_tables = sql_catalog.sql_search_tables
sql_catalog.sql_search_tables = sql_catalog.sql_search_tables + [
'alternate_roles_and_users']
# Configure sql method to insert this table
sql_catalog.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod(
id='z_catalog_alternate_roles_and_users_list',
title='',
connection_id='erp5_sql_connection',
arguments="\n".join(['uid', 'alternate_security_uid']),
template="""REPLACE INTO alternate_roles_and_users VALUES
<dtml-in prefix="loop" expr="_.range(_.len(uid))">
( <dtml-sqlvar expr="uid[loop_item]" type="int">,
<dtml-sqlvar expr="alternate_security_uid[loop_item]" type="int" optional>
)<dtml-unless sequence-end>,</dtml-unless>
</dtml-in>""")
current_sql_catalog_object_list = sql_catalog.sql_catalog_object_list
sql_catalog.sql_catalog_object_list = \
current_sql_catalog_object_list + \
('z_catalog_alternate_roles_and_users_list',)
# configure Alternate local roles group id to go in alternate_security_uid
current_sql_catalog_security_uid_columns =\
sql_catalog.sql_catalog_security_uid_columns
sql_catalog.sql_catalog_security_uid_columns = (
' | security_uid',
'Alternate | alternate_security_uid', )
# add category
self.portal.portal_categories.local_role_group.newContent(
portal_type='Category',
reference = 'Alternate',
id = 'Alternate')
# configure security on person, each user will be able to see his own
# person thanks to an Auditor role on "Alternate" local roles group id.
self.portal.portal_types.Person.newContent(
portal_type='Role Information',
role_name='Auditor',
role_base_category_script_id='ERP5Type_getSecurityCategoryFromSelf',
role_base_category='agent',
local_role_group_value=self.portal.portal_categories.local_role_group.Alternate.getRelativeUrl())
self.portal.portal_caches.clearAllCache()
self.tic()
try:
# create two persons and users
user1 = self.portal.person_module.newContent(portal_type='Person',
reference='user1')
user1.newContent(portal_type='Assignment').open()
user1.updateLocalRolesOnSecurityGroups()
self.assertEquals(user1.__ac_local_roles__.get('user1'), ['Auditor'])
user2 = self.portal.person_module.newContent(portal_type='Person',
reference='user2')
user2.newContent(portal_type='Assignment').open()
user2.updateLocalRolesOnSecurityGroups()
self.assertEquals(user2.__ac_local_roles__.get('user2'), ['Auditor'])
self.tic()
# security_uid_dict in catalog contains entries for user1 and user2:
user1_alternate_security_uid = sql_catalog.security_uid_dict[
('Alternate', ('user:user1', 'user:user1:Auditor'))]
bob_alternate_security_uid = sql_catalog.security_uid_dict[
('Alternate', ('user:user2', 'user:user2:Auditor'))]
# those entries are in alternate security table
alternate_roles_and_users = sql_connection.manage_test(
"SELECT * from alternate_roles_and_users").dictionaries()
self.assertTrue(dict(uid=user1.getUid(),
alternate_security_uid=user1_alternate_security_uid) in
alternate_roles_and_users)
self.assertTrue(dict(uid=user2.getUid(),
alternate_security_uid=bob_alternate_security_uid) in
alternate_roles_and_users)
# low level check of the security query of a logged in user
self.login('user1')
security_query = self.portal.portal_catalog.getSecurityQuery()
# This query is a complex query wrapping another complex query with a
# criterion on altenate_security_uid. This check is quite low level and
# is subject to change.
security_uid_query = security_query.query_list[0]
alternate_security_query, = [q for q in
security_query.query_list[0].query_list if
q.kw.get('alternate_security_uid')]
self.assertEquals([user1_alternate_security_uid],
alternate_security_query.kw['alternate_security_uid'])
# high level check that that logged in user can see document
self.assertEquals([user1],
[o.getObject() for o in self.portal.portal_catalog(portal_type='Person')])
# also with local_roles= argument which is used in worklists
self.assertEquals([user1],
[o.getObject() for o in self.portal.portal_catalog(portal_type='Person',
local_roles='Auditor')])
# searches still work for other users
self.login('ERP5TypeTestCase')
self.assertSameSet([user1, user2],
[o.getObject() for o in
self.portal.portal_catalog(portal_type='Person')])
finally:
# restore catalog configuration
sql_catalog.sql_search_tables = current_sql_search_tables
sql_catalog.sql_catalog_object_list = current_sql_catalog_object_list
sql_catalog.sql_catalog_security_uid_columns =\
current_sql_catalog_security_uid_columns
self.portal.portal_types.Person.manage_delObjects(
[role.getId() for role in
self.portal.portal_types.Person.contentValues(
portal_type='Role Information')])
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5CatalogSecurityUidOptimization))
return suite
......@@ -580,6 +580,29 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
self.assertFalse('Assignee' in user.getRolesInContext(obj))
self.abort()
def testLocalRolesGroupId(self):
"""Assigning a role with local roles group id.
"""
self.portal.portal_categories.local_role_group.newContent(
portal_type='Category',
reference = 'Alternate',
id = 'Alternate')
self._getTypeInfo().newContent(portal_type='Role Information',
role_name='Assignor',
local_role_group_value=self.portal.portal_categories.local_role_group.Alternate.getRelativeUrl(),
role_category=self.defined_category)
self.loginAsUser(self.username)
user = getSecurityManager().getUser()
obj = self._makeOne()
self.assertEqual(['Assignor'], obj.__ac_local_roles__.get('F1_G1_S1'))
self.assertTrue('Assignor' in user.getRolesInContext(obj))
self.assertEqual(set([('F1_G1_S1', 'Assignor')]),
obj.__ac_local_roles_group_id_dict__.get('Alternate'))
self.abort()
def testDynamicLocalRole(self):
"""Test simple case of setting a dynamic role.
The site category is not defined explictly the role, and will have the
......
......@@ -183,5 +183,4 @@ class RoleInformation(XMLObject):
return group_id_role_dict
InitializeClass(RoleInformation)
......@@ -89,7 +89,25 @@ class LocalRoleAssignorMixIn(object):
else:
user_name = getSecurityManager().getUser().getId()
group_id_role_dict = self.getLocalRolesFor(ob, user_name)
group_id_role_dict = {}
local_roles_group_id_group_id = {}
# Merge results from applicable roles
for role_generator in self.getFilteredRoleListFor(ob):
local_roles_group_id = ''
if getattr(role_generator, 'getLocalRoleGroupValue', None) is not None:
# only some role generators like 'Role Information' support it
local_role_group = role_generator.getLocalRoleGroupValue()
if local_role_group is not None:
# role definitions use category to classify different types of local roles
# so use their categories' reference
local_roles_group_id = local_role_group.getReference() or local_role_group.getId()
for group_id, role_list \
in role_generator.getLocalRolesFor(ob, user_name).iteritems():
group_id_role_dict.setdefault(group_id, set()).update(role_list)
if local_roles_group_id:
for role in role_list:
# Feed local_roles_group_id_group_id with local roles assigned to a group
local_roles_group_id_group_id.setdefault(local_roles_group_id, set()).update(((group_id, role),))
## Update role assignments to groups
# Save the owner
......@@ -101,24 +119,17 @@ class LocalRoleAssignorMixIn(object):
for group, role_list in group_id_role_dict.iteritems():
if role_list:
ac_local_roles[group] = list(role_list)
if local_roles_group_id_group_id:
ob.__ac_local_roles_group_id_dict__ = local_roles_group_id_group_id
elif getattr(aq_base(ob),
'__ac_local_roles_group_id_dict__', None) is not None:
delattr(ob, '__ac_local_roles_group_id_dict__')
## Make sure that the object is reindexed
if reindex:
ob.reindexObjectSecurity()
security.declarePrivate("getLocalRolesFor")
def getLocalRolesFor(self, ob, user_name=None):
"""Compute the security that should be applied on an object
Returned value is a dict: {groud_id: role_name_set, ...}
"""
group_id_role_dict = {}
# Merge results from applicable roles
for role in self.getFilteredRoleListFor(ob):
for group_id, role_list \
in role.getLocalRolesFor(ob, user_name).iteritems():
group_id_role_dict.setdefault(group_id, set()).update(role_list)
return group_id_role_dict
security.declarePrivate('getFilteredRoleListFor')
def getFilteredRoleListFor(self, ob=None):
"""Return all role generators applicable to the object."""
......
......@@ -39,7 +39,7 @@ class ILocalRoleGenerator(Interface):
Returned value is a dict: {groud_id: role_name_set, ...}
"""
class ILocalRoleAssignor(ILocalRoleGenerator):
class ILocalRoleAssignor(Interface):
"""
"""
def updateLocalRolesOnDocument(ob, user_name=None, reindex=True):
......
......@@ -36,6 +36,7 @@ from Persistence import Persistent
from Products.ERP5Type.Globals import PersistentMapping
from itertools import izip
from MySQLdb import ProgrammingError, OperationalError
from DateTime import DateTime
def DCWorkflowDefinition_notifyWorkflowMethod(self, ob, transition_list, args=None, kw=None):
'''
......@@ -89,7 +90,6 @@ DCWorkflowDefinition.notifySuccess = DCWorkflowDefinition_notifySuccess
WORKLIST_METADATA_KEY = 'metadata'
SECURITY_PARAMETER_ID = 'local_roles'
SECURITY_COLUMN_ID = 'security_uid'
COUNT_COLUMN_TITLE = 'count'
class ExclusionList(list):
......@@ -145,7 +145,7 @@ def updateWorklistSetDict(worklist_set_dict, workflow_worklist_key, valid_criter
[workflow_worklist_key] = valid_criterion_dict
def groupWorklistListByCondition(worklist_dict, sql_catalog,
getSecurityUidListAndRoleColumnDict=None):
getSecurityUidDictAndRoleColumnDict=None):
"""
Get a list of dict of WorklistVariableMatchDict grouped by compatible
conditions.
......@@ -185,7 +185,7 @@ def groupWorklistListByCondition(worklist_dict, sql_catalog,
for workflow_id, worklist in worklist_dict.iteritems():
for worklist_id, worklist_match_dict in worklist.iteritems():
workflow_worklist_key = '/'.join((workflow_id, worklist_id))
if getSecurityUidListAndRoleColumnDict is None:
if getSecurityUidDictAndRoleColumnDict is None:
valid_criterion_dict, metadata = getValidCriterionDict(
worklist_match_dict=worklist_match_dict,
sql_catalog=sql_catalog,
......@@ -201,15 +201,18 @@ def groupWorklistListByCondition(worklist_dict, sql_catalog,
security_kw = {}
if len(security_parameter):
security_kw[SECURITY_PARAMETER_ID] = security_parameter
uid_list, role_column_dict, local_role_column_dict = \
getSecurityUidListAndRoleColumnDict(**security_kw)
uid_dict, role_column_dict, local_role_column_dict = \
getSecurityUidDictAndRoleColumnDict(**security_kw)
for key, value in local_role_column_dict.items():
worklist_match_dict[key] = [value]
if len(uid_list):
uid_list.sort()
role_column_dict[SECURITY_COLUMN_ID] = uid_list
catalog_security_uid_groups_columns_dict = \
sql_catalog.getSQLCatalogSecurityUidGroupsColumnsDict()
for local_roles_group_id, uid_list in uid_dict.iteritems():
role_column_dict[
catalog_security_uid_groups_columns_dict[local_roles_group_id]] = uid_list
# Make sure every item is a list - or a tuple
for security_column_id in role_column_dict.iterkeys():
value = role_column_dict[security_column_id]
......@@ -271,6 +274,8 @@ def generateNestedQuery(priority_list, criterion_dict,
**{my_criterion_id: criterion_value})
if isinstance(criterion_value, ExclusionTuple):
query = NegatedQuery(query)
query = ComplexQuery(operator='OR',
*(query, Query(**{my_criterion_id: None})))
append(ComplexQuery(query, subcriterion_query, operator='AND'))
else:
possible_value_list = tuple()
......@@ -296,6 +301,8 @@ def generateNestedQuery(priority_list, criterion_dict,
if len(impossible_value_list):
query = Query(operator='IN', **{my_criterion_id: impossible_value_list})
query = NegatedQuery(query)
query = ComplexQuery(operator='OR',
*(query, Query(**{my_criterion_id: None})))
value_query_list.append(query)
append(ComplexQuery(operator='AND', *value_query_list))
if len(query_list):
......@@ -334,6 +341,17 @@ def getWorklistListQuery(grouped_worklist_dict):
assert COUNT_COLUMN_TITLE not in total_criterion_id_dict
return (total_criterion_id_list, query)
# XXX: see ZMySQLDA/db.py:DB.defs
# This dict is used to tell which cast to apply to worklist parameters to get
# values comparable with SQL result content.
_sql_cast_dict = {
'i': long,
'l': long,
'n': float,
'd': DateTime,
}
_sql_cast_fallback = str
def sumCatalogResultByWorklist(grouped_worklist_dict, catalog_result):
"""
Return a dict regrouping each worklist's result, extracting it from
......@@ -354,8 +372,8 @@ def sumCatalogResultByWorklist(grouped_worklist_dict, catalog_result):
if len(catalog_result) > 0:
# Transtype all worklist definitions where needed
criterion_id_list = []
class_dict = dict(((name, value.__class__) for name, value in \
izip(catalog_result.names(), catalog_result[0])))
class_dict = dict(((name, _sql_cast_dict.get(x['type'], _sql_cast_fallback))
for name, x in catalog_result.data_dictionary().iteritems()))
for criterion_dict in grouped_worklist_dict.itervalues():
for criterion_id, criterion_value_list in criterion_dict.iteritems():
if type(criterion_value_list) is not ExclusionList:
......@@ -462,8 +480,8 @@ def WorkflowTool_listActions(self, info=None, object=None, src__=False):
else:
search_result = portal_catalog.unrestrictedSearchResults
select_expression_prefix = 'count(*) as %s' % (COUNT_COLUMN_TITLE, )
getSecurityUidListAndRoleColumnDict = \
portal_catalog.getSecurityUidListAndRoleColumnDict
getSecurityUidDictAndRoleColumnDict = \
portal_catalog.getSecurityUidDictAndRoleColumnDict
security_query_cache_dict = {}
def _getWorklistActionList():
worklist_result_dict = {}
......@@ -474,8 +492,8 @@ def WorkflowTool_listActions(self, info=None, object=None, src__=False):
groupWorklistListByCondition(
worklist_dict=worklist_dict,
sql_catalog=sql_catalog,
getSecurityUidListAndRoleColumnDict=\
getSecurityUidListAndRoleColumnDict)
getSecurityUidDictAndRoleColumnDict=\
getSecurityUidDictAndRoleColumnDict)
if src__:
action_list = []
for grouped_worklist_dict in worklist_list_grouped_by_condition:
......@@ -587,7 +605,8 @@ def WorkflowTool_refreshWorklistCache(self):
sql_catalog = portal_catalog.getSQLCatalog()
table_column_id_set = ImmutableSet(
[COUNT_COLUMN_TITLE] + self.Base_getWorklistTableColumnIDList())
security_column_id_list = ['security_uid'] + \
security_column_id_list = list(
sql_catalog.getSQLCatalogSecurityUidGroupsColumnsDict().values()) + \
[x[1] for x in sql_catalog.getSQLCatalogRoleKeysList()] + \
[x[1] for x in sql_catalog.getSQLCatalogLocalRoleKeysList()]
(worklist_list_grouped_by_condition, worklist_metadata) = \
......
......@@ -524,6 +524,14 @@ class Catalog(Folder,
'a monovalued local role',
'type': 'lines',
'mode': 'w' },
{ 'id': 'sql_catalog_security_uid_columns',
'title': 'Security Uid Columns',
'description': 'A list of mappings "local_roles_group_id | security_uid_column"'
' local_roles_group_id will be the name of a local roles'
' group, and security_uid_column is the corresponding'
' column in catalog table',
'type': 'lines',
'mode': 'w' },
{ 'id': 'sql_catalog_table_vote_scripts',
'title': 'Table vote scripts',
'description': 'Scripts helping column mapping resolution',
......@@ -575,6 +583,7 @@ class Catalog(Folder,
sql_catalog_scriptable_keys = ()
sql_catalog_role_keys = ()
sql_catalog_local_role_keys = ()
sql_catalog_security_uid_columns = (' | security_uid',)
sql_catalog_table_vote_scripts = ()
sql_catalog_raise_error_on_uid_check = True
......@@ -626,6 +635,18 @@ class Catalog(Folder,
role_key_dict[role.strip()] = column.strip()
return role_key_dict.items()
def getSQLCatalogSecurityUidGroupsColumnsDict(self):
"""
Return a mapping of local_roles_group_id name to the name of the column
storing corresponding security_uid.
The default mappiny is {'': 'security_uid'}
"""
local_roles_group_id_dict = {}
for local_roles_group_id_key in self.sql_catalog_security_uid_columns:
local_roles_group_id, column = local_roles_group_id_key.split('|')
local_roles_group_id_dict[local_roles_group_id.strip()] = column.strip()
return local_roles_group_id_dict
def getSQLCatalogLocalRoleKeysList(self):
"""
Return the list of local role keys.
......@@ -765,38 +786,41 @@ class Catalog(Folder,
self.subject_set_uid_dict = OIBTree()
self.subject_set_uid_index = None
security.declarePrivate('getSecurityUid')
def getSecurityUid(self, wrapped_object):
security.declarePrivate('getSecurityUidDict')
def getSecurityUidDict(self, wrapped_object):
"""
Cache a uid for each security permission
Return a tuple with a security uid (string) and a new tuple content the
roles and users if not exist already.
With the roles of object, search the security_uid associate in the
catalog_innodb:
- if the security not exist a security uid is generated with id_tool
or security_uid_index property and
return the new security_uid and the tuple contains the new roles
to add the roles in roles_and_user table of the database.
- if the security exist the security uid is returned and the second
element is None for not recreate the security in roles_and_user
table of the database.
We try to create a unique security (to reduce number of lines)
and to assign security only to root document
returns a tuple with a dict of security uid by local group id, and a tuple
containing optimised_roles_and_users that might have been created.
"""
# Get security information
allowed_roles_and_users = tuple(wrapped_object.allowedRolesAndUsers())
# Make sure no duplicates
if getattr(aq_base(self), 'security_uid_dict', None) is None:
self._clearSecurityCache()
elif self.security_uid_dict.has_key(allowed_roles_and_users):
return (self.security_uid_dict[allowed_roles_and_users], None)
id_tool = getattr(self.getPortalObject(), 'portal_ids', None)
optimised_roles_and_users = []
local_roles_group_id_to_security_uid_mapping= dict()
# Get security information
for local_roles_group_id, allowed_roles_and_users in\
wrapped_object.getLocalRolesGroupIdDict().iteritems():
allowed_roles_and_users = tuple(sorted(allowed_roles_and_users))
key = (local_roles_group_id, allowed_roles_and_users)
if self.security_uid_dict.has_key(key):
local_roles_group_id_to_security_uid_mapping[local_roles_group_id] \
= self.security_uid_dict[key]
elif self.security_uid_dict.has_key(allowed_roles_and_users)\
and not local_roles_group_id:
# This key is present in security_uid_dict without
# local_roles_group_id, it has been inserted before
# local_roles_group_id were introduced.
local_roles_group_id_to_security_uid_mapping[local_roles_group_id] = \
self.security_uid_dict[allowed_roles_and_users]
else:
# If the id_tool is there, it is better to use it, it allows
# to create many new security uids by the same time
# because with this tool we are sure that we will have 2 different
# uids if two instances are doing this code in the same time
id_tool = getattr(self.getPortalObject(), 'portal_ids', None)
if id_tool is not None:
default = 1
# We must keep compatibility with existing sites
......@@ -818,8 +842,17 @@ class Catalog(Folder,
previous_security_uid = previous_security_uid()
security_uid = previous_security_uid + 1
self.security_uid_index = security_uid
self.security_uid_dict[allowed_roles_and_users] = security_uid
return (security_uid, allowed_roles_and_users)
self.security_uid_dict[key] = security_uid
local_roles_group_id_to_security_uid_mapping[local_roles_group_id]\
= security_uid
# If some optimised_roles_and_users are returned by this method it
# means that new entries will have to be added to roles_and_users table.
for user in allowed_roles_and_users:
optimised_roles_and_users.append((security_uid, local_roles_group_id, user))
return (local_roles_group_id_to_security_uid_mapping, optimised_roles_and_users)
def getRoleAndSecurityUidList(self):
"""
......@@ -828,7 +861,8 @@ class Catalog(Folder,
"""
result = []
extend = result.extend
for role_list, security_uid in getattr(aq_base(self), 'security_uid_dict', {}).iteritems():
for role_list, security_uid in getattr(
aq_base(self), 'security_uid_dict', {}).iteritems():
extend([(role, security_uid) for role in role_list])
return result
......
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