Commit 480a9fec authored by Alexandre Boeglin's avatar Alexandre Boeglin

Added the possibility to filter which skins and scripts from the portal_skins

folder can be applied on each portal type.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@3206 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 456ab1c3
......@@ -39,6 +39,9 @@ from RoleInformation import ori
from zLOG import LOG
import re
action_basename_re = re.compile("\/([^\/\?]+)(\?.+)?$")
ERP5TYPE_ROLE_INIT_SCRIPT = 'ERP5Type_initLocalRoleMapping'
class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
......@@ -64,7 +67,7 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
+ RoleProviderBase.manage_options
+ SimpleItemWithProperties.manage_options[1:]
)
_properties = (TypeInformation._basic_properties + (
{'id':'factory', 'type': 'string', 'mode':'w',
'label':'Product factory method'},
......@@ -96,6 +99,13 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
, 'label':'Base Categories'
, 'select_variable':'getBaseCategoryList'
},
{'id':'filter_actions', 'type': 'boolean', 'mode':'w',
'label':'Filter actions?'},
{'id':'allowed_action_list'
, 'type': 'lines'
, 'mode':'w'
, 'label':'Allowed actions'
},
))
property_sheet_list = ()
......@@ -104,13 +114,15 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
product = 'ERP5Type'
immediate_view = 'view'
hidden_content_type_list = ()
filter_actions = 0
allowed_action_list = []
#
# Acquisition editing interface
#
_actions_form = DTMLFile( 'editToolsActions', _dtmldir )
security.declarePublic('hideFromAddMenu')
def hidenFromAddMenu(self):
"""
......@@ -130,15 +142,15 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
'container', using 'id' as its id. Return the object.
"""
ob = FactoryTypeInformation.constructInstance(self, container, id, *args, **kw)
# Try to find the local role init script
init_role_script = getattr(ob, ERP5TYPE_ROLE_INIT_SCRIPT, None)
if init_role_script is not None:
# Retrieve applicable roles
role_mapping = self.getFilteredRoleListFor(object = self) # kw provided in order to take any appropriate action
# Call the local role init script
init_role_script(role_mapping = role_mapping, **kw)
init_role_script(role_mapping = role_mapping, **kw)
if self.init_script:
# Acquire the init script in the context of this object
init_script = getattr(ob, self.init_script)
......@@ -164,6 +176,29 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
"""
return self.hidden_content_type_list
security.declareProtected(ERP5Permissions.AccessContentsInformation, 'isActionAllowed')
def isActionAllowed( self, action=None ):
"""
Return list of allowed actions.
You can define a 'allowed_action_list' property (as lines) on the portal_types object
to define actions that will be available for all portal types.
"""
if not self.filter_actions :
return 1 # everything is allowed
global_allowed_action_list = list(self.portal_types.getProperty('allowed_action_list', []))
action_list = list(self.allowed_action_list) + global_allowed_action_list
for ob_action in self._actions :
action_basename = action_basename_re.search(ob_action.action.text).group(1)
if len(action_basename) :
action_list.append(action_basename_re.search(ob_action.action.text).group(1))
LOG('isActionAllowed for %s :' % self.title_or_id(), 0, 'looking for %s in %s : %s' % (action, action_list, action in action_list))
if action in action_list :
return 1
return 0
security.declareProtected(ERP5Permissions.AccessContentsInformation, 'getBaseCategoryList')
def getBaseCategoryList( self ):
result = self.portal_categories.getBaseCategoryList()
......@@ -197,7 +232,7 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
break
else:
folder = aq_parent(aq_inner(folder))
ec = createExprContext(folder, portal, object)
roles = []
append = roles.append
......@@ -215,9 +250,9 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
if not filtered_roles.has_key(id):
filtered_roles[id] = []
filtered_roles[id].append(role)
return filtered_roles
#
# Helper methods
#
......@@ -230,13 +265,13 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
else:
for i in r:
append(i)
def manage_editProperties(self, REQUEST):
"""
Method overload
Method overload
Reset _aq_dynamic if property_sheet definition has changed)
XXX This is only good in single thread mode.
In ZEO environment, we should call portal_activities
in order to implement a broadcast update
......@@ -249,7 +284,7 @@ class ERP5TypeInformation( FactoryTypeInformation, RoleProviderBase ):
base_category_list != self.base_category_list:
from Products.ERP5Type.Base import _aq_reset
_aq_reset() # XXX We should also call it whenever we change workflow defitino
return result
return result
security.declareProtected( ERP5Permissions.ManagePortal, 'manage_editLocalRolesForm' )
def manage_editLocalRolesForm( self, REQUEST, manage_tabs_message=None ):
......
......@@ -929,22 +929,22 @@ class OrderedPickler(Pickler):
write(MARK + DICT)
self.memoize(obj)
item_list = obj.items() # New version by JPS for sorting
item_list = obj.items() # New version by JPS for sorting
item_list.sort(lambda a, b: cmp(a[0], b[0])) # New version by JPS for sorting
self._batch_setitems(item_list.__iter__())
dispatch[DictionaryType] = save_dict
if not PyStringMap is None:
dispatch[PyStringMap] = save_dict
def reorderPickle(jar, p):
from ZODB.ExportImport import Ghost, Unpickler, Pickler, StringIO, persistent_id
oids = {}
storage = jar._storage
new_oid = storage.new_oid
store = storage.store
def persistent_load(ooid,
Ghost=Ghost,
oids=oids, wrote_oid=oids.has_key,
......@@ -958,13 +958,13 @@ def reorderPickle(jar, p):
Ghost=Ghost()
Ghost.oid=ooid
return Ghost
# Reorder pickle by doing I/O
pfile = StringIO(p)
pfile = StringIO(p)
unpickler=Unpickler(pfile)
unpickler.persistent_load=persistent_load
unpickler.persistent_load=persistent_load
newp=StringIO()
pickler=OrderedPickler(newp,1)
pickler.persistent_id=persistent_id
......@@ -974,8 +974,8 @@ def reorderPickle(jar, p):
pickler.dump(obj)
p=newp.getvalue()
return obj, p
def XMLrecord(oid, plen, p, id_mapping):
def XMLrecord(oid, plen, p, id_mapping):
# Proceed as usual
q=ppml.ToXMLUnpickler
f=StringIO(p)
......@@ -1022,24 +1022,24 @@ def exportXML(jar, oid, file=None):
else:
o, p = reorderPickle(jar, p)
reordered_pickle.append((oid, o, p))
XMLrecord(oid,len(p),p, id_mapping)
XMLrecord(oid,len(p),p, id_mapping)
# Determine new oids added to the list after reference calculation
old_oids = tuple(oids)
ref(p, oids)
new_oids = []
for i in oids:
for i in oids:
if i not in old_oids: new_oids.append(i)
# Sort new oids based on id of object
new_oidict = {}
# Sort new oids based on id of object
new_oidict = {}
for oid in new_oids:
try:
p, serial = load(oid, version)
o, p = reorderPickle(jar, p)
new_oidict[oid] = getattr(o, 'id', None)
except:
except:
new_oidict[oid] = None # Ick, a broken reference
new_oids.sort(lambda a,b: cmp(new_oidict[a], new_oidict[b]))
# Build new sorted oids
new_oids.sort(lambda a,b: cmp(new_oidict[a], new_oidict[b]))
# Build new sorted oids
oids = list(old_oids) + new_oids
# Do real export
for (oid, o, p) in reordered_pickle:
......@@ -1091,16 +1091,16 @@ class Scalar:
# The value is Immutable - let us add it the the immutable mapping
# to reduce the number of unreadable references
self.mapping.setImmutable(self.id, Immutable(value = result))
return result
return result
ppml.Scalar = Scalar
class Immutable:
def __init__(self, value):
self.value = value
def getValue(self):
return self.value
return self.value
class String(Scalar):
def __init__(self, v, mapping, encoding=''):
......@@ -1130,7 +1130,7 @@ class String(Scalar):
# The value is Immutable - let us add it the the immutable mapping
# to reduce the number of unreadable references
self.mapping.setImmutable(self.id, Immutable(value = result))
return result
return result
ppml.String = String
......@@ -1253,11 +1253,11 @@ class Reference(Scalar):
self.mapping = mapping
def __str__(self, indent=0):
v=self._v
name=string.lower(self.__class__.__name__)
name=string.lower(self.__class__.__name__)
#LOG('Reference', 0, str(v))
if self.mapping.hasImmutable(v):
return self.mapping.getImmutable(v).getValue()
#LOG('noImmutable', 0, "%s mapped to %s" % (v, self.mapping[v]))
return self.mapping.getImmutable(v).getValue()
#LOG('noImmutable', 0, "%s mapped to %s" % (v, self.mapping[v]))
self.mapping.mark(v)
return '%s<%s id="%s"/>\n' % (' '*indent,name,self.mapping[v])
......@@ -1275,13 +1275,13 @@ class Object(Sequence):
ppml.Object = Object
class IdentityMapping:
def __init__(self):
self.immutable = {}
def resetMapping(self):
pass
def __getitem__(self, id):
return id
......@@ -1306,7 +1306,7 @@ class IdentityMapping:
def hasImmutable(self, k):
return self.immutable.has_key(k)
ppml.IdentityMapping = IdentityMapping
class MinimalMapping(IdentityMapping):
......@@ -1326,7 +1326,7 @@ class MinimalMapping(IdentityMapping):
self.last_id = 1
self.converted_aka = {}
self.marked_reference = {}
def __getitem__(self, id):
id = str(id)
split_id = id.split('.')
......@@ -1579,7 +1579,7 @@ class ToXMLUnpickler(Unpickler):
def __init__(self, func):
self.func = func
def __call__(self, context):
def __call__(self, context):
#LOG('LogCall', 0, 'self.stack = %r, func = %s' % (context.stack, self.func.__name__))
return self.func(context)
......@@ -1777,7 +1777,7 @@ def SQLVar_render(self, md):
else:
raise ValueError, (
'Invalid datetime value for <em>%s</em>: %r' % (name, v))
try:
if hasattr(v, 'ISO'):
v=v.ISO()
......@@ -1789,7 +1789,7 @@ def SQLVar_render(self, md):
return 'null'
raise ValueError, (
'Invalid datetime value for <em>%s</em>: %r' % (name, v))
v=md.getitem('sql_quote__',0)(v)
# End of patch
else:
......@@ -1801,7 +1801,7 @@ def SQLVar_render(self, md):
raise ValueError, (
'Invalid string value for <em>%s</em>' % name)
# End of patch
if not isinstance(v, (str, unicode)):
v=str(v)
if not v and t=='nb':
......@@ -1848,3 +1848,48 @@ def reindexObject(self, idxs=[], *args, **kw):
catalog.reindexObject(self, idxs=idxs, *args, **kw)
CMFCatalogAware.reindexObject = reindexObject
##########################################
# ERP5TypeInformation filtered actions
from ZPublisher.BaseRequest import BaseRequest
BaseRequest.old_traverse = BaseRequest.traverse
def new_traverse(self, path, response=None, validated_hook=None) :
import time
start_time = time.time()
object = self.old_traverse(path, response=response, validated_hook=validated_hook)
object_id_getter = getattr(object, 'getId', None)
if response is None: response=self.response
LOG('My Traverse absolute_url', 0, path )
if hasattr(object, 'unrestrictedTraverse') :
portal_skins = aq_base(object.unrestrictedTraverse('portal_skins', default=None))
if portal_skins is not None :
skin_list = []
for skin_folder in portal_skins.getSkinPath(portal_skins.getDefaultSkin()).split(',') :
skin_folder_object = getattr(portal_skins, skin_folder, None)
if skin_folder_object is not None :
for skin in skin_folder_object._objects :
skin_list.append(skin['id'])
if object_id_getter is not None :
object_id = object_id_getter()
if object_id in skin_list :
parent = object.aq_parent
portal_type_getter = getattr(parent, 'getPortalType', None)
if portal_type_getter is not None :
portal_type_object = getattr(object.portal_types, portal_type_getter(), None)
if portal_type_object is not None :
allowed = portal_type_object.isActionAllowed(action=object_id)
LOG('My Traverse allowed', 0, repr(( path, object, allowed )))
if allowed == 0 :
LOG('My Traverse failed after TIMEEEEEEEEEEE', 0, time.time() - start_time)
response.unauthorized()
LOG('My Traverse succeded after TIMEEEEEEEEEEE', 0, time.time() - start_time)
return object
BaseRequest.traverse = new_traverse
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