[gen] klass.creators can now be a method that either returns a list of global roles allowed to create instances of this class, or a boolean indicating if the currently logged user can create instances of this class or not. [gen] Bugfixes.

This commit is contained in:
Gaetan Delannay 2013-09-22 16:33:32 +02:00
parent e1b83574c5
commit 1f901e5545
6 changed files with 64 additions and 55 deletions

View file

@ -74,7 +74,7 @@ class Field:
# Displays a field label. # Displays a field label.
pxLabel = Px('''<label if="field.hasLabel and (field.type != 'Action')" pxLabel = Px('''<label if="field.hasLabel and (field.type != 'Action')"
lfor="field.name">::zobj.translate('label', field=field)</label>''') lfor=":field.name">::zobj.translate('label', field=field)</label>''')
# Displays a field description. # Displays a field description.
pxDescription = Px('''<span if="field.hasDescr" pxDescription = Px('''<span if="field.hasDescr"

View file

@ -185,14 +185,16 @@ class Transition:
# triggered if user has at least one of those roles and if all # triggered if user has at least one of those roles and if all
# functions return True. # functions return True.
hasRole = None hasRole = None
for roleOrFunction in self.condition: for condition in self.condition:
if isinstance(roleOrFunction, basestring): # "Unwrap" role names from Role instances.
if isinstance(condition, Role): condition = condition.name
if isinstance(condition, basestring): # It is a role
if hasRole == None: if hasRole == None:
hasRole = False hasRole = False
if user.has_role(roleOrFunction, obj): if user.has_role(condition, obj):
hasRole = True hasRole = True
elif type(roleOrFunction) == types.FunctionType: else: # It is a method
if not roleOrFunction(wf, obj.appy()): if not condition(wf, obj.appy()):
return False return False
if hasRole != False: if hasRole != False:
return True return True

View file

@ -158,17 +158,19 @@ class ClassDescriptor(Descriptor):
return res return res
def getCreators(self): def getCreators(self):
'''Gets the specific creators defined for this class.''' '''Gets the specific creators defined for this class, excepted if
attribute "creators" does not contain a list or roles.'''
res = [] res = []
if self.klass.__dict__.has_key('creators') and self.klass.creators: if not hasattr(self.klass, 'creators'): return res
for creator in self.klass.creators: if not isinstance(self.klass.creators, list): return res
if isinstance(creator, gen.Role): for creator in self.klass.creators:
if creator.local: if isinstance(creator, gen.Role):
raise 'Local role "%s" cannot be used as a creator.' % \ if creator.local:
creator.name raise 'Local role "%s" cannot be used as a creator.' % \
res.append(creator) creator.name
else: res.append(creator)
res.append(gen.Role(creator)) else:
res.append(gen.Role(creator))
return res return res
def getCreateMean(self, type='Import'): def getCreateMean(self, type='Import'):

View file

@ -501,7 +501,9 @@ class ZopeGenerator(Generator):
allRoles[role.name] = role allRoles[role.name] = role
# Gather roles from "creators" attributes from every class # Gather roles from "creators" attributes from every class
for cDescr in self.getClasses(include='all'): for cDescr in self.getClasses(include='all'):
for role in cDescr.getCreators(): creators = cDescr.getCreators()
if not creators: continue
for role in creators:
if role.name not in allRoles: if role.name not in allRoles:
allRoles[role.name] = role allRoles[role.name] = role
res = allRoles.values() res = allRoles.values()

View file

@ -269,24 +269,18 @@ class ToolMixin(BaseMixin):
elems = sortMethod(elems) elems = sortMethod(elems)
return [importParams.headers, elems] return [importParams.headers, elems]
def showPortlet(self, context, layoutType): def showPortlet(self, obj, layoutType):
'''When must the portlet be shown?''' '''When must the portlet be shown? p_obj and p_layoutType can be None
if we are not browing any objet (ie, we are on the home page).'''
# Not on 'edit' pages. # Not on 'edit' pages.
if layoutType == 'edit': return if layoutType == 'edit': return
if context and (context.id == 'ui'): context = context.getParentNode()
res = True res = True
if context and hasattr(context.aq_base, 'appy'): if obj and hasattr(obj, 'showPortlet'):
appyObj = context.appy() res = obj.showPortlet()
try:
res = appyObj.showPortlet()
except AttributeError:
res = True
else: else:
appyObj = self.appy() tool = self.appy()
try: if hasattr(tool, 'showPortletAt'):
res = appyObj.showPortletAt(context) res = tool.showPortletAt(self.REQUEST['ACTUAL_URL'])
except AttributeError:
res = True
return res return res
def getObject(self, uid, appy=False, brain=False): def getObject(self, uid, appy=False, brain=False):
@ -300,23 +294,14 @@ class ToolMixin(BaseMixin):
return res.appy() return res.appy()
def getAllowedValue(self): def getAllowedValue(self):
'''Gets, for the currently logged user, the value for index '''Gets, for the current user, the value of index "Allowed".'''
"Allowed".'''
tool = self.appy()
user = self.getUser() user = self.getUser()
rq = tool.request
# Get the user roles # Get the user roles
res = rq.userRoles res = user.getRoles()
# Add role "Anonymous" # Get the user logins
if 'Anonymous' not in res: res.append('Anonymous') if user.login != 'anon':
# Add the user id if not anonymous for login in user.getLogins():
userId = user.login res.append('user:%s' % login)
if userId != 'anon': res.append('user:%s' % userId)
# Add group ids
try:
res += ['user:%s' % g for g in rq.zopeUser.groups.keys()]
except AttributeError, ae:
pass # The Zope admin does not have this attribute.
return res return res
def executeQuery(self, className, searchName=None, startNumber=0, def executeQuery(self, className, searchName=None, startNumber=0,
@ -499,21 +484,39 @@ class ToolMixin(BaseMixin):
res[means.id] = means res[means.id] = means
return res return res
def userMaySearch(self, rootClass): def userMaySearch(self, klass):
'''May the logged user search among instances of p_rootClass ?''' '''May the user search among instances of root p_klass ?'''
# When editing a form, one should avoid annoying the user with this. # When editing a form, one should avoid annoying the user with this.
url = self.REQUEST['ACTUAL_URL'] url = self.REQUEST['ACTUAL_URL']
if url.endswith('/edit') or url.endswith('/do'): return if url.endswith('/edit') or url.endswith('/do'): return
if 'maySearch' in rootClass.__dict__: if hasattr(klass, 'maySearch'): return klass.maySearch(self.appy())
return pythonClass.rootClass(self.appy())
return True return True
def userMayCreate(self, klass): def userMayCreate(self, klass):
'''May the logged user create instances of p_klass ?''' '''May the logged user create instances of p_klass ? This information
allowedRoles = getattr(klass, 'creators', None) or \ can be defined on p_klass, in static attribute "creators".
self.getProductConfig().appConfig.defaultCreators 1. If this attr holds a list, we consider it to be a list of roles,
and we check that the user has at least one of those roles.
2. If this attr holds a boolean, we consider that the user can create
instances of this class if the boolean is True.
3. If this attr stores a method, we execute the method, and via its
result, we fall again in cases 1 or 2.
If p_klass does not define this attr "creators", we will use a
default list of roles as defined in the config.'''
# Get the value of attr "creators", or a default value if not present.
if hasattr(klass, 'creators'):
creators = klass.creators
else:
creators = self.getProductConfig().appConfig.defaultCreators
# Resolve case (3): if "creators" is a method, execute it.
if callable(creators): creators = creators(self.appy())
# Resolve case (2)
if isinstance(creators, bool) or not creators: return creators
# Resolve case (1): checks whether the user has at least one of the
# roles listed in "creators".
for role in self.getUser().getRoles(): for role in self.getUser().getRoles():
if role in allowedRoles: if role in creators:
return True return True
def onImportObjects(self): def onImportObjects(self):

View file

@ -91,7 +91,7 @@ class AbstractWrapper(object):
dummy=setattr(req, 'pxContext', _ctx_); dummy=setattr(req, 'pxContext', _ctx_);
lang=ztool.getUserLanguage(); q=ztool.quote; lang=ztool.getUserLanguage(); q=ztool.quote;
layoutType=ztool.getLayoutType(); layoutType=ztool.getLayoutType();
showPortlet=ztool.showPortlet(zobj, layoutType); showPortlet=ztool.showPortlet(obj, layoutType);
dir=ztool.getLanguageDirection(lang); dir=ztool.getLanguageDirection(lang);
discreetLogin=ztool.getProductConfig(True).discreetLogin; discreetLogin=ztool.getProductConfig(True).discreetLogin;
dleft=(dir == 'ltr') and 'left' or 'right'; dleft=(dir == 'ltr') and 'left' or 'right';