Example #1
0
    def _extractAction(self, properties, index):
        """ Extract an ActionInformation from the funky form properties.
        """
        id = str(properties.get('id_%d' % index, ''))
        title = str(properties.get('name_%d' % index, ''))
        action = str(properties.get('action_%d' % index, ''))
        condition = str(properties.get('condition_%d' % index, ''))
        category = str(properties.get('category_%d' % index, ''))
        visible = bool(properties.get('visible_%d' % index, False))
        permissions = properties.get('permission_%d' % index, ())

        if not title:
            raise ValueError('A title is required.')

        if category == '':
            category = 'object'

        if isinstance(permissions, basestring):
            permissions = (permissions, )

        return ActionInformation(id=id,
                                 title=title,
                                 action=action,
                                 condition=condition,
                                 permissions=permissions,
                                 category=category,
                                 visible=visible)
Example #2
0
 def addAction(self,
               id,
               name,
               action,
               condition,
               permission,
               category,
               visible=1,
               REQUEST=None):
     """
     Adds an action to the list.
     """
     al = self._actions[:]
     if not name:
         raise ValueError('A name is required.')
     if action:
         a_expr = Expression(text=str(action))
     else:
         a_expr = ''
     if condition:
         c_expr = Expression(text=str(condition))
     else:
         c_expr = ''
     al.append(
         ActionInformation(id=str(id),
                           title=str(name),
                           action=a_expr,
                           condition=c_expr,
                           permissions=(str(permission), ),
                           category=str(category),
                           visible=int(visible)))
     self._actions = al
     if REQUEST is not None:
         return self.manage_editActionsForm(REQUEST,
                                            manage_tabs_message='Added.')
Example #3
0
    def changeActions(self, properties=None, REQUEST=None):
        """
        Changes the _actions.
        """
        if properties is None:
            properties = REQUEST
        actions = self._actions[:]
        for idx in range(len(actions)):
            s_idx = str(idx)
            action = {
                'id': str(properties.get('id_' + s_idx, '')),
                'name': str(properties.get('name_' + s_idx, '')),
                'action': str(properties.get('action_' + s_idx, '')),
                'condition': str(properties.get('condition_' + s_idx, '')),
                'permissions': (properties.get('permission_' + s_idx, ()), ),
                'category': str(properties.get('category_' + s_idx, 'object')),
                'visible': properties.get('visible_' + s_idx, 0),
            }
            if not action['name']:
                raise ValueError('A name is required.')

# DM: do not override shared element!
# a = actions[idx]

            class Empty:
                pass

            a = Empty()

            a.id = action['id']
            a.title = action['name']
            if action['action'] is not '':
                a._action = Expression(text=action['action'])
            else:
                a._action = ''
            if action['condition'] is not '':
                a.condition = Expression(text=action['condition'])
            else:
                a.condition = ''
            a.permissions = action['permissions']
            a.category = action['category']
            a.visible = action['visible']

            # DM - unshare! severe sharing bug via class variable "_actions"
            actions[idx] = ActionInformation(
                id=a.id,
                title=a.title,
                action=a._action,
                condition=a.condition,
                permissions=a.permissions,
                category=a.category,
                visible=a.visible,
            )

        self._actions = actions
        if REQUEST is not None:
            return self.manage_editActionsForm(
                REQUEST, manage_tabs_message='Actions changed.')
Example #4
0
    def _extractAction( self, properties, index ):

        """ Extract an ActionInformation from the funky form properties.
        """
        id          = str( properties.get( 'id_%d'          % index, '' ) )
        name        = str( properties.get( 'name_%d'        % index, '' ) )
        action      = str( properties.get( 'action_%d'      % index, '' ) )
        condition   = str( properties.get( 'condition_%d'   % index, '' ) )
        category    = str( properties.get( 'category_%d'    % index, '' ))
        visible     =      properties.get( 'visible_%d'     % index, 0  )
        permissions =      properties.get( 'permission_%d'  % index, () )

        if not name:
            raise ValueError('A name is required.')

        if action is not '':
            action = Expression( text=action )

        if condition is not '':
            condition = Expression( text=condition )

        if category == '':
            category = 'object'

        if type( visible ) is not type( 0 ):
            try:
                visible = int( visible )
            except:
                visible = 0

        if type( permissions ) is type( '' ):
            permissions = ( permissions, )

        return ActionInformation( id=id
                                , title=name
                                , action=action
                                , condition=condition
                                , permissions=permissions
                                , category=category
                                , visible=visible
                                )
Example #5
0
    def addAction( self
                 , id
                 , name
                 , action
                 , condition
                 , permission
                 , category
                 , visible=1
                 , REQUEST=None
                 ):
        """ Add an action to our list.
        """
        if not name:
            raise ValueError('A name is required.')

        a_expr = action and Expression(text=str(action)) or ''
        c_expr = condition and Expression(text=str(condition)) or ''

        if type( permission ) != type( () ):
            permission = permission and (str(permission),) or ()

        new_actions = self._cloneActions()

        new_action = ActionInformation( id=str(id)
                                      , title=str(name)
                                      , action=a_expr
                                      , condition=c_expr
                                      , permissions=permission
                                      , category=str(category)
                                      , visible= not not visible
                                      )

        new_actions.append( new_action )
        self._actions = tuple( new_actions )

        if REQUEST is not None:
            return self.manage_editActionsForm(
                REQUEST, manage_tabs_message='Added.')
Example #6
0
    def addAction( self
                 , id
                 , name
                 , action
                 , condition
                 , permission
                 , category
                 , visible=1
                 , REQUEST=None
                 ):
        """ Add an action to our list.
        """
        if not name:
            raise ValueError('A name is required.')

        action = action and str(action) or ''
        condition = condition and str(condition) or ''

        if not isinstance(permission, tuple):
            permission = (str(permission),)

        new_actions = self._cloneActions()

        new_action = ActionInformation( id=str(id)
                                      , title=str(name)
                                      , category=str(category)
                                      , condition=condition
                                      , permissions=permission
                                      , visible=bool(visible)
                                      , action=action
                                      )

        new_actions.append( new_action )
        self._actions = tuple( new_actions )

        if REQUEST is not None:
            return self.manage_editActionsForm(
                REQUEST, manage_tabs_message='Added.')
Example #7
0
    def listActions(self, info=None, object=None):
        """ List all the actions defined by a provider.
        """
        if object is None and info is not None:
            # BBB (according to the interface)
            object = info.content
        if object is None:
            # The tool itself doesn't provide any action
            return ()

        actions = []
        for mid in globalBrowserMenuService._registry.keys():
            menu = getMenu(mid, object, self.REQUEST)
            for entry in menu:
                # The action needs a unique name, so we'll build one
                # from the object_id and the action url. That is sure
                # to be unique.
                action = str(entry['action'])
                if object is None:
                    act_id = 'action_%s' % action
                else:
                    act_id = 'action_%s_%s' % (object.getId(), action)

                if entry['filter'] is None:
                    filter = None
                else:
                    filter = Expression(text=str(entry['filter']))

                act = ActionInformation(id=act_id,
                                        title=str(entry['title']),
                                        action=Expression(text='string:%s' %
                                                          action),
                                        condition=filter,
                                        category=str(mid),
                                        visible=1)
                actions.append(act)
        return tuple(actions)
Example #8
0
class UndoTool (UniqueObject, SimpleItem, ActionProviderBase):
    """ This tool is used to undo changes.
    """

    __implements__ = (IUndoTool, ActionProviderBase.__implements__)

    id = 'portal_undo'
    meta_type = 'CMF Undo Tool'
    _actions = (ActionInformation(id='undo'
                                , title='Undo'
                                , action=Expression(
               text='string: ${portal_url}/undo_form')
                                , condition=Expression(
               text='member') 
                                , permissions=(ListUndoableChanges,)
                                , category='global'
                                , visible=1
                                 )
               ,
               )

    security = ClassSecurityInfo()

    manage_options = ( ActionProviderBase.manage_options +
                       SimpleItem.manage_options +
                       ({ 'label' : 'Overview', 'action' : 'manage_overview' }
                     , 
                     ))
    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile( 'explainUndoTool', _dtmldir )

    #
    #   'portal_undo' interface methods
    #
    security.declareProtected(ListUndoableChanges, 'listUndoableTransactionsFor')
    def listUndoableTransactionsFor(self, object,
                                    first_transaction=None,
                                    last_transaction=None,
                                    PrincipiaUndoBatchSize=None):
        '''Lists all transaction IDs the user is allowed to undo.
        '''
        # arg list for undoable_transactions() changed in Zope 2.2.
        portal = self.aq_inner.aq_parent
        transactions = portal.undoable_transactions(
            first_transaction=first_transaction,
            last_transaction=last_transaction,
            PrincipiaUndoBatchSize=PrincipiaUndoBatchSize)
        for t in transactions:
            # Ensure transaction ids don't have embedded LF.
            t['id'] = t['id'].replace('\n', '')
        if not _checkPermission(ManagePortal, portal):
            # Filter out transactions done by other members of the portal.
            user_id = _getAuthenticatedUser(self).getId()
            transactions = filter(
                lambda record, user_id=user_id:
                record['user_name'].split()[-1] == user_id,
                transactions
                )
        return transactions

    security.declarePublic('undo')
    def undo(self, object, transaction_info):
        """
            Undo the list of transactions passed in 'transaction_info',
            first verifying that the current user is allowed to undo them.
        """
        # Belt and suspenders:  make sure that the user is actually
        # allowed to undo the transation(s) in transaction_info.

        xids = {}  # set of allowed transaction IDs

        allowed = self.listUndoableTransactionsFor( object )

        for xid in map( lambda x: x['id'], allowed ):
            xids[xid] = 1

        if type( transaction_info ) == type( '' ):
            transaction_info = [ transaction_info ]

        for tinfo in transaction_info:
            if not xids.get( tinfo, None ):
                raise Unauthorized

        object.manage_undo_transactions(transaction_info)
Example #9
0
class ActionsTool(UniqueObject, OFS.Folder.Folder, ActionProviderBase):
    """
        Weave together the various sources of "actions" which are apropos
        to the current user and context.
    """
    id = 'portal_actions'
    _actions = [ActionInformation(id='folderContents'
                                , title='Folder contents'
                                , action=Expression(
               text='string: ${folder_url}/folder_contents')
                                , condition=Expression(
               text='python: folder is not object') 
                                , permissions=('List folder contents',)
                                , category='object'
                                , visible=1
                                 )
              , ActionInformation(id='folderContents'
                                , title='Folder contents'
                                , action=Expression(
               text='string: ${folder_url}/folder_contents')
                                , condition=Expression(
               text='python: folder is object')
                                , permissions=('List folder contents',)
                                , category='folder'
                                , visible=1
                                 )]

    meta_type = 'CMF Actions Tool'

    action_providers = ('portal_membership'
                      , 'portal_actions'
                      , 'portal_registration'
                      , 'portal_discussion'
                      , 'portal_undo'
                      , 'portal_syndication'
                      , 'portal_workflow'
                      , 'portal_properties')

    security = ClassSecurityInfo()

    manage_options = ( ActionProviderBase.manage_options +
                      ({'label' : 'Action Providers', 'action' : 'manage_actionProviders'}
                     ,   { 'label' : 'Overview', 'action' : 'manage_overview' }
                     ,
                     ) + OFS.Folder.Folder.manage_options
                     ) 

    #
    #   ZMI methods
    #
    security.declareProtected( CMFCorePermissions.ManagePortal
                             , 'manage_overview' )
    manage_overview = DTMLFile( 'explainActionsTool', _dtmldir )
    manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir)


    #
    # Programmatically manipulate the list of action providers
    #

    security.declarePrivate('listActions')
    def listActions(self, info=None):
        """
        Lists actions available through the tool.
        """
        return self._actions

    security.declareProtected( CMFCorePermissions.ManagePortal
                             , 'listActionProviders'
                             )
    def listActionProviders(self):
       """ returns a sequence of action providers known by this tool """
       return self.action_providers

    security.declareProtected(CMFCorePermissions.ManagePortal
                            , 'manage_aproviders')
    def manage_aproviders(self
                        , apname=''
                        , chosen=()
                        , add_provider=0
                        , del_provider=0
                        , REQUEST=None):
        """
        Manage TTW Action Providers
        """
        providers = list(self.listActionProviders())
        new_providers = []
        if add_provider:
            providers.append(apname)
        elif del_provider:
            for item in providers:
                if item not in chosen:
                    new_providers.append(item)
            providers = new_providers
        self.action_providers = providers
        if REQUEST is not None:
            return self.manage_actionProviders(self
                                             , REQUEST
                                             , manage_tabs_message='Properties changed.')
        


    security.declareProtected( CMFCorePermissions.ManagePortal
                             , 'addActionProvider'
                             )
    def addActionProvider( self, provider_name ):
        """ add the name of a new action provider """
        if hasattr( self, provider_name ):
            p_old = self.action_providers
            p_new = p_old + ( provider_name, )
            self.action_providers = p_new

    security.declareProtected( CMFCorePermissions.ManagePortal
                             , 'deleteActionProvider'
                             )
    def deleteActionProvider( self, provider_name ):
        """ remove an action provider """
        if provider_name in self.action_providers:
            p_old = list( self.action_providers )
            del p_old[p_old.index( provider_name)]
            self.action_providers = tuple( p_old )

    #
    #   'portal_actions' interface methods
    #

    def _listActions(self,append,object,info,ec):
        a = object.listActions(info)
        if a and type(a[0]) is not type({}):
            for ai in a:
                if ai.testCondition(ec):
                    append(ai.getAction(ec))
        else:
            for i in a:
                append(i)
        
    security.declarePublic('listFilteredActionsFor')
    def listFilteredActionsFor(self, object=None):
        '''Gets all actions available to the user and returns a mapping
        containing user actions, object actions, and global actions.
        '''
        portal = aq_parent(aq_inner(self))
        if object is None or not hasattr(object, 'aq_base'):
            folder = portal
        else:
            folder = object
            # Search up the containment hierarchy until we find an
            # object that claims it's a folder.
            while folder is not None:
                if getattr(aq_base(folder), 'isPrincipiaFolderish', 0):
                    # found it.
                    break
                else:
                    folder = aq_parent(aq_inner(folder))
        ec = createExprContext(folder, portal, object)
        actions = []
        append = actions.append
        info = oai(self, folder, object)
        # Include actions from specific tools.
        for provider_name in self.listActionProviders():
            provider = getattr(self, provider_name)
            self._listActions(append,provider,info,ec)

        # Include actions from object.
        if object is not None:
            base = aq_base(object)
            types_tool = getToolByName( self, 'portal_types' )
            ti = types_tool.getTypeInfo( object )
            if ti is not None:
                defs = ti.getActions()
                if defs:
                    c_url = object.absolute_url()
                    for d in defs:
                        a = d['action']
                        if a:
                            url = c_url + '/' + a
                        else:
                            url = c_url
                        actions.append({
                            'id': d.get('id', None),
                            'name': d['name'],
                            'action': d['action'],
                            'url': url,
                            'permissions': d['permissions'],
                            'category': d.get('category', 'object'),
                            'visible': d.get('visible', 1),
                            })                
            if hasattr(base, 'listActions'):
                self._listActions(append,object,info,ec)
                

        # Reorganize the actions by category,
        # filtering out disallowed actions.
        filtered_actions={'user':[],
                          'folder':[],
                          'object':[],
                          'global':[],
                          'workflow':[],
                          }
        for action in actions:
            category = action['category']
            permissions = action.get('permissions', None)
            visible = action.get('visible', 1)
            if not visible:
                continue
            verified = 0
            if not permissions:
                # This action requires no extra permissions.
                verified = 1
            else:
                if category in ('object', 'workflow') and object is not None:
                    context = object
                elif category == 'folder' and folder is not None:
                    context = folder
                else:
                    context = portal
                for permission in permissions:
                    # The user must be able to match at least one of
                    # the listed permissions.
                    if _checkPermission(permission, context):
                        verified = 1
                        break
            if verified:
                catlist = filtered_actions.get(category, None)
                if catlist is None:
                    filtered_actions[category] = catlist = []
                # Filter out duplicate actions by identity...
                if not action in catlist:
                    catlist.append(action)
                # ...should you need it, here's some code that filters
                # by equality (use instead of the two lines above)
                #if not [a for a in catlist if a==action]:
                #    catlist.append(action)
        return filtered_actions

    # listFilteredActions() is an alias.
    security.declarePublic('listFilteredActions')
    listFilteredActions = listFilteredActionsFor
Example #10
0
class ActionsTool(UniqueObject, Folder, ActionProviderBase):
    """
        Weave together the various sources of "actions" which are apropos
        to the current user and context.
    """

    __implements__ = (IActionsTool, ActionProviderBase.__implements__)

    id = 'portal_actions'
    meta_type = 'CMF Actions Tool'
    _actions = (ActionInformation(id='folderContents'
                                , title='Folder contents'
                                , action=Expression(
               text='string:${folder_url}/folder_contents')
                                , condition=Expression(
               text='python: folder is not object')
                                , permissions=(ListFolderContents,)
                                , category='folder'
                                , visible=1
                                 )
               ,
               )

    action_providers = ( 'portal_membership'
                       , 'portal_actions'
                       , 'portal_registration'
                       , 'portal_types'
                       , 'portal_discussion'
                       , 'portal_undo'
                       , 'portal_syndication'
                       , 'portal_workflow'
                       , 'portal_properties'
                       )

    security = ClassSecurityInfo()

    manage_options = ( ActionProviderBase.manage_options
                     + ( { 'label' : 'Action Providers'
                         , 'action' : 'manage_actionProviders'
                         }
                       , { 'label' : 'Overview'
                         , 'action' : 'manage_overview'
                         }
                     ) + Folder.manage_options
                     )

    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile( 'explainActionsTool', _dtmldir )
    manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir)

    security.declareProtected(ManagePortal, 'manage_aproviders')
    def manage_aproviders(self
                        , apname=''
                        , chosen=()
                        , add_provider=0
                        , del_provider=0
                        , REQUEST=None):
        """
        Manage action providers through-the-web.
        """
        providers = list(self.listActionProviders())
        new_providers = []
        if add_provider:
            providers.append(apname)
        elif del_provider:
            for item in providers:
                if item not in chosen:
                    new_providers.append(item)
            providers = new_providers
        self.action_providers = tuple(providers)
        if REQUEST is not None:
            return self.manage_actionProviders(self , REQUEST
                          , manage_tabs_message='Providers changed.')

    #
    #   Programmatically manipulate the list of action providers
    #
    security.declareProtected(ManagePortal, 'listActionProviders')
    def listActionProviders(self):
        """ List the ids of all Action Providers queried by this tool.
        """
        return self.action_providers

    security.declareProtected(ManagePortal, 'addActionProvider')
    def addActionProvider( self, provider_name ):
        """ Add an Action Provider id to the providers queried by this tool.
        """
        ap = list( self.action_providers )
        if hasattr( self, provider_name ) and provider_name not in ap:
            ap.append( provider_name )
            self.action_providers = tuple( ap )

    security.declareProtected(ManagePortal, 'deleteActionProvider')
    def deleteActionProvider( self, provider_name ):
        """ Delete an Action Provider id from providers queried by this tool.
        """
        ap = list( self.action_providers )
        if provider_name in ap:
            ap.remove( provider_name )
            self.action_providers = tuple( ap )

    #
    #   'portal_actions' interface methods
    #
    security.declarePublic('listFilteredActionsFor')
    def listFilteredActionsFor(self, object=None):
        """ List all actions available to the user.
        """
        actions = []

        # Include actions from specific tools.
        for provider_name in self.listActionProviders():
            provider = getattr(self, provider_name)
            if IActionProvider.isImplementedBy(provider):
                actions.extend( provider.listActionInfos(object=object) )
            else:
                # for Action Providers written for CMF versions before 1.5
                actions.extend( self._listActionInfos(provider, object) )

        # Include actions from object.
        if object is not None:
            base = aq_base(object)
            if IActionProvider.isImplementedBy(base):
                actions.extend( object.listActionInfos(object=object) )
            elif hasattr(base, 'listActions'):
                # for objects written for CMF versions before 1.5
                actions.extend( self._listActionInfos(object, object) )

        # Reorganize the actions by category.
        filtered_actions={'user':[],
                          'folder':[],
                          'object':[],
                          'global':[],
                          'workflow':[],
                          }

        for action in actions:
            catlist = filtered_actions.setdefault(action['category'], [])
            catlist.append(action)

        return filtered_actions

    # listFilteredActions() is an alias.
    security.declarePublic('listFilteredActions')
    listFilteredActions = listFilteredActionsFor

    #
    #   Helper method for backwards compatibility
    #
    def _listActionInfos(self, provider, object):
        """ for Action Providers written for CMF versions before 1.5
        """
        warn('ActionProvider interface not up to date. In CMF 2.0 '
             'portal_actions will ignore listActions() of \'%s\'.'
             % provider.getId(),
             DeprecationWarning)
        info = self._getOAI(object)
        actions = provider.listActions(info)

        action_infos = []
        if actions and not isinstance(actions[0], dict):
            ec = self._getExprContext(object)
            for ai in actions:
                if not ai.getVisibility():
                    continue
                permissions = ai.getPermissions()
                if permissions:
                    category = ai.getCategory()
                    if (object is not None and
                        (category.startswith('object') or
                         category.startswith('workflow'))):
                        context = object
                    elif (info['folder'] is not None and
                          category.startswith('folder')):
                        context = info['folder']
                    else:
                        context = info['portal']
                    for permission in permissions:
                        allowed = _checkPermission(permission, context)
                        if allowed:
                            break
                    if not allowed:
                        continue
                if not ai.testCondition(ec):
                    continue
                action_infos.append( ai.getAction(ec) )
        else:
            for i in actions:
                if not i.get('visible', 1):
                    continue
                permissions = i.get('permissions', None)
                if permissions:
                    category = i['category']
                    if (object is not None and
                        (category.startswith('object') or
                         category.startswith('workflow'))):
                        context = object
                    elif (info['folder'] is not None and
                          category.startswith('folder')):
                        context = info['folder']
                    else:
                        context = info['portal']

                    for permission in permissions:
                        allowed = _checkPermission(permission, context)
                        if allowed:
                            break
                    if not allowed:
                        continue
                action_infos.append(i)
        return action_infos
Example #11
0
class ActionsTool(UniqueObject, Folder, ActionProviderBase):
    """
        Weave together the various sources of "actions" which are apropos
        to the current user and context.
    """
    id = 'portal_actions'
    _actions = [
        ActionInformation(
            id='folderContents',
            title='Folder contents',
            action=Expression(text='string: ${folder_url}/folder_contents'),
            condition=Expression(text='python: folder is not object'),
            permissions=('List folder contents', ),
            category='object',
            visible=1),
        ActionInformation(
            id='folderContents',
            title='Folder contents',
            action=Expression(text='string: ${folder_url}/folder_contents'),
            condition=Expression(text='python: folder is object'),
            permissions=('List folder contents', ),
            category='folder',
            visible=1)
    ]

    meta_type = 'CMF Actions Tool'

    action_providers = ('portal_membership', 'portal_actions',
                        'portal_registration', 'portal_discussion',
                        'portal_undo', 'portal_syndication', 'portal_workflow',
                        'portal_properties')

    security = ClassSecurityInfo()

    manage_options = (ActionProviderBase.manage_options +
                      ({
                          'label': 'Action Providers',
                          'action': 'manage_actionProviders'
                      }, {
                          'label': 'Overview',
                          'action': 'manage_overview'
                      }) + Folder.manage_options)

    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile('explainActionsTool', _dtmldir)
    manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir)

    security.declareProtected(ManagePortal, 'manage_aproviders')

    def manage_aproviders(self,
                          apname='',
                          chosen=(),
                          add_provider=0,
                          del_provider=0,
                          REQUEST=None):
        """
        Manage action providers through-the-web.
        """
        providers = list(self.listActionProviders())
        new_providers = []
        if add_provider:
            providers.append(apname)
        elif del_provider:
            for item in providers:
                if item not in chosen:
                    new_providers.append(item)
            providers = new_providers
        self.action_providers = tuple(providers)
        if REQUEST is not None:
            return self.manage_actionProviders(
                self, REQUEST, manage_tabs_message='Properties changed.')

    #
    #   ActionProvider interface
    #
    security.declarePrivate('listActions')

    def listActions(self, info=None):
        """
        Return a list of actions available through the tool.
        """
        return self._actions

    #
    # Programmatically manipulate the list of action providers
    #
    security.declareProtected(ManagePortal, 'listActionProviders')

    def listActionProviders(self):
        """
       Return a sequence of names of action providers known by this tool.
       """
        return self.action_providers

    security.declareProtected(ManagePortal, 'addActionProvider')

    def addActionProvider(self, provider_name):
        """
        Add the name of a new action provider.
        """
        ap = list(self.action_providers)[:]
        if hasattr(self, provider_name) and provider_name not in ap:
            ap.append(provider_name)
            self.action_providers = tuple(ap)

    security.declareProtected(ManagePortal, 'deleteActionProvider')

    def deleteActionProvider(self, provider_name):
        """
        Remove an action provider.
        """
        if provider_name in self.action_providers:
            ap = list(self.action_providers)
            ap.remove(provider_name)
            self.action_providers = tuple(ap)

    #
    #   'portal_actions' interface methods
    #
    security.declarePublic('listFilteredActionsFor')

    def listFilteredActionsFor(self, object=None):
        '''Gets all actions available to the user and returns a mapping
        containing user actions, object actions, and global actions.
        '''
        portal = aq_parent(aq_inner(self))
        if object is None or not hasattr(object, 'aq_base'):
            folder = portal
        else:
            folder = object
            # Search up the containment hierarchy until we find an
            # object that claims it's a folder.
            while folder is not None:
                if getattr(aq_base(folder), 'isPrincipiaFolderish', 0):
                    # found it.
                    break
                else:
                    folder = aq_parent(aq_inner(folder))
        ec = createExprContext(folder, portal, object)
        actions = []
        append = actions.append
        info = oai(self, folder, object)
        # Include actions from specific tools.
        for provider_name in self.listActionProviders():
            provider = getattr(self, provider_name)
            self._listActions(append, provider, info, ec)

        # Include actions from object.
        if object is not None:
            base = aq_base(object)
            types_tool = getToolByName(self, 'portal_types')
            # we might get None back from getTypeInfo.  We construct
            # a dummy TypeInformation object here in that case (the 'or'
            # case).  This prevents us from needing to check the condition.
            ti = types_tool.getTypeInfo(object) or TypeInformation('Dummy')
            defs = ti.getActions()
            url = object_url = object.absolute_url()
            for d in defs:
                # we can't modify or expose the original actionsd... this
                # stems from the fact that getActions returns a ref to the
                # actual dictionary used to store actions instead of a
                # copy.  We copy it here to prevent it from being modified.
                d = d.copy()
                d['id'] = d.get('id', None)
                if d['action']:
                    url = '%s/%s' % (object_url, d['action'])
                d['url'] = url
                d['category'] = d.get('category', 'object')
                d['visible'] = d.get('visible', 1)
                actions.append(d)

            if hasattr(base, 'listActions'):
                self._listActions(append, object, info, ec)

        # Reorganize the actions by category,
        # filtering out disallowed actions.
        filtered_actions = {
            'user': [],
            'folder': [],
            'object': [],
            'global': [],
            'workflow': [],
        }
        for action in actions:
            category = action['category']
            permissions = action.get('permissions', None)
            visible = action.get('visible', 1)
            if not visible:
                continue
            verified = 0
            if not permissions:
                # This action requires no extra permissions.
                verified = 1
            else:
                if (object is not None
                        and (category.startswith('object')
                             or category.startswith('workflow'))):
                    context = object
                elif (folder is not None and category.startswith('folder')):
                    context = folder
                else:
                    context = portal
                for permission in permissions:
                    # The user must be able to match at least one of
                    # the listed permissions.
                    if _checkPermission(permission, context):
                        verified = 1
                        break
            if verified:
                catlist = filtered_actions.get(category, None)
                if catlist is None:
                    filtered_actions[category] = catlist = []
                # Filter out duplicate actions by identity...
                if not action in catlist:
                    catlist.append(action)
                # ...should you need it, here's some code that filters
                # by equality (use instead of the two lines above)
                #if not [a for a in catlist if a==action]:
                #    catlist.append(action)
        return filtered_actions

    # listFilteredActions() is an alias.
    security.declarePublic('listFilteredActions')
    listFilteredActions = listFilteredActionsFor

    #
    #   Helper methods
    #
    security.declarePrivate('_listActions')

    def _listActions(self, append, object, info, ec):

        a = object.listActions(info)
        if a and type(a[0]) is not type({}):
            for ai in a:
                if ai.testCondition(ec):
                    append(ai.getAction(ec))
        else:
            for i in a:
                append(i)
Example #12
0
class UndoTool(UniqueObject, SimpleItem, ActionProviderBase):
    id = 'portal_undo'
    meta_type = 'CMF Undo Tool'
    # This tool is used to undo changes.
    _actions = [
        ActionInformation(
            id='undo',
            title='Undo',
            action=Expression(text='string: ${portal_url}/undo_form'),
            condition=Expression(text='member'),
            permissions=(ListUndoableChanges, ),
            category='global',
            visible=1)
    ]

    security = ClassSecurityInfo()

    manage_options = (ActionProviderBase.manage_options +
                      SimpleItem.manage_options + ({
                          'label': 'Overview',
                          'action': 'manage_overview'
                      }, ))
    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile('explainUndoTool', _dtmldir)

    security.declarePrivate('listActions')

    def listActions(self, info=None):
        """
        List actions available through tool
        """
        return self._actions

    #
    #   'portal_undo' interface methods
    #
    security.declareProtected(ListUndoableChanges,
                              'listUndoableTransactionsFor')

    def listUndoableTransactionsFor(self,
                                    object,
                                    first_transaction=None,
                                    last_transaction=None,
                                    PrincipiaUndoBatchSize=None):
        '''Lists all transaction IDs the user is allowed to undo.
        '''
        # arg list for undoable_transactions() changed in Zope 2.2.
        portal = self.aq_inner.aq_parent
        transactions = portal.undoable_transactions(
            first_transaction=first_transaction,
            last_transaction=last_transaction,
            PrincipiaUndoBatchSize=PrincipiaUndoBatchSize)
        if not _checkPermission('Manage portal', portal):
            # Filter out transactions done by other members of the portal.
            user_name = _getAuthenticatedUser(self).getUserName()
            transactions = filter(lambda record, user_name=user_name: split(
                record['user_name'])[-1] == user_name,
                                  transactions)
        return transactions

    security.declareProtected(UndoChanges, 'undo')

    def undo(self, object, transaction_info):
        '''Performs an undo operation.
        '''
        object.manage_undo_transactions(transaction_info)
Example #13
0
class ActionsTool(UniqueObject, IFAwareObjectManager, OrderedFolder,
                  ActionProviderBase):
    """
        Weave together the various sources of "actions" which are apropos
        to the current user and context.
    """

    __implements__ = (IActionsTool, OrderedFolder.__implements__,
                      ActionProviderBase.__implements__)

    id = 'portal_actions'
    meta_type = 'CMF Actions Tool'
    _product_interfaces = (IActionCategory, )
    _actions = (ActionInformation(
        id='folderContents',
        title='Folder contents',
        action=Expression(text='string:${folder_url}/folder_contents'),
        condition=Expression(text='python: folder is not object'),
        permissions=(ListFolderContents, ),
        category='folder',
        visible=1), )

    action_providers = ('portal_membership', 'portal_actions',
                        'portal_registration', 'portal_types',
                        'portal_discussion', 'portal_undo',
                        'portal_syndication', 'portal_workflow',
                        'portal_properties')

    security = ClassSecurityInfo()

    manage_options = ((OrderedFolder.manage_options[0],
                       ActionProviderBase.manage_options[0], {
                           'label': 'Action Providers',
                           'action': 'manage_actionProviders'
                       }, {
                           'label': 'Overview',
                           'action': 'manage_overview'
                       }) + OrderedFolder.manage_options[2:])

    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile('explainActionsTool', _dtmldir)
    manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir)

    security.declareProtected(ManagePortal, 'manage_aproviders')

    def manage_aproviders(self,
                          apname='',
                          chosen=(),
                          add_provider=0,
                          del_provider=0,
                          REQUEST=None):
        """
        Manage action providers through-the-web.
        """
        providers = list(self.listActionProviders())
        new_providers = []
        if add_provider:
            providers.append(apname)
        elif del_provider:
            for item in providers:
                if item not in chosen:
                    new_providers.append(item)
            providers = new_providers
        self.action_providers = tuple(providers)
        if REQUEST is not None:
            return self.manage_actionProviders(
                self, REQUEST, manage_tabs_message='Providers changed.')

    security.declareProtected(ManagePortal, 'manage_editActionsForm')

    def manage_editActionsForm(self, REQUEST, manage_tabs_message=None):
        """ Show the 'Actions' management tab.
        """
        actions = [ai.getMapping() for ai in self._actions]

        # possible_permissions is in AccessControl.Role.RoleManager.
        pp = self.possible_permissions()
        return self._actions_form(self,
                                  REQUEST,
                                  actions=actions,
                                  possible_permissions=pp,
                                  management_view='Actions',
                                  manage_tabs_message=manage_tabs_message)

    #
    #   ActionProvider interface
    #
    security.declarePrivate('listActions')

    def listActions(self, info=None, object=None):
        """ List all the actions defined by a provider.
        """
        actions = list(self._actions)
        for category in self.objectValues():
            actions.extend(category.listActions())
        return tuple(actions)

    #
    #   Programmatically manipulate the list of action providers
    #
    security.declareProtected(ManagePortal, 'listActionProviders')

    def listActionProviders(self):
        """ List the ids of all Action Providers queried by this tool.
        """
        return self.action_providers

    security.declareProtected(ManagePortal, 'addActionProvider')

    def addActionProvider(self, provider_name):
        """ Add an Action Provider id to the providers queried by this tool.
        """
        ap = list(self.action_providers)
        if hasattr(self, provider_name) and provider_name not in ap:
            ap.append(provider_name)
            self.action_providers = tuple(ap)

    security.declareProtected(ManagePortal, 'deleteActionProvider')

    def deleteActionProvider(self, provider_name):
        """ Delete an Action Provider id from providers queried by this tool.
        """
        ap = list(self.action_providers)
        if provider_name in ap:
            ap.remove(provider_name)
            self.action_providers = tuple(ap)

    #
    #   'portal_actions' interface methods
    #
    security.declarePublic('listFilteredActionsFor')

    def listFilteredActionsFor(self, object=None):
        """ List all actions available to the user.
        """
        actions = []

        # Include actions from specific tools.
        for provider_name in self.listActionProviders():
            provider = getattr(self, provider_name)
            if IActionProvider.isImplementedBy(provider):
                actions.extend(provider.listActionInfos(object=object))

        # Include actions from object.
        if object is not None:
            if IActionProvider.isImplementedBy(object):
                actions.extend(object.listActionInfos(object=object))

        # Reorganize the actions by category.
        filtered_actions = {
            'user': [],
            'folder': [],
            'object': [],
            'global': [],
            'workflow': [],
        }

        for action in actions:
            catlist = filtered_actions.setdefault(action['category'], [])
            catlist.append(action)

        return filtered_actions
Example #14
0
class ActionsTool(UniqueObject, Folder, ActionProviderBase):
    """
        Weave together the various sources of "actions" which are apropos
        to the current user and context.
    """

    __implements__ = (IActionsTool, ActionProviderBase.__implements__)

    id = 'portal_actions'
    meta_type = 'CMF Actions Tool'
    _actions = (ActionInformation(
        id='folderContents',
        title='Folder contents',
        action=Expression(text='string:${folder_url}/folder_contents'),
        condition=Expression(text='python: folder is not object'),
        permissions=(ListFolderContents, ),
        category='folder',
        visible=1), )

    action_providers = ('portal_membership', 'portal_actions',
                        'portal_registration', 'portal_types',
                        'portal_discussion', 'portal_undo',
                        'portal_syndication', 'portal_workflow',
                        'portal_properties')

    security = ClassSecurityInfo()

    manage_options = (ActionProviderBase.manage_options +
                      ({
                          'label': 'Action Providers',
                          'action': 'manage_actionProviders'
                      }, {
                          'label': 'Overview',
                          'action': 'manage_overview'
                      }) + Folder.manage_options)

    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile('explainActionsTool', _dtmldir)
    manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir)

    security.declareProtected(ManagePortal, 'manage_aproviders')

    def manage_aproviders(self,
                          apname='',
                          chosen=(),
                          add_provider=0,
                          del_provider=0,
                          REQUEST=None):
        """
        Manage action providers through-the-web.
        """
        providers = list(self.listActionProviders())
        new_providers = []
        if add_provider:
            providers.append(apname)
        elif del_provider:
            for item in providers:
                if item not in chosen:
                    new_providers.append(item)
            providers = new_providers
        self.action_providers = tuple(providers)
        if REQUEST is not None:
            return self.manage_actionProviders(
                self, REQUEST, manage_tabs_message='Providers changed.')

    #
    #   Programmatically manipulate the list of action providers
    #
    security.declareProtected(ManagePortal, 'listActionProviders')

    def listActionProviders(self):
        """ List the ids of all Action Providers queried by this tool.
        """
        return self.action_providers

    security.declareProtected(ManagePortal, 'addActionProvider')

    def addActionProvider(self, provider_name):
        """ Add an Action Provider id to the providers queried by this tool.
        """
        ap = list(self.action_providers)
        if hasattr(self, provider_name) and provider_name not in ap:
            ap.append(provider_name)
            self.action_providers = tuple(ap)

    security.declareProtected(ManagePortal, 'deleteActionProvider')

    def deleteActionProvider(self, provider_name):
        """ Delete an Action Provider id from providers queried by this tool.
        """
        ap = list(self.action_providers)
        if provider_name in ap:
            ap.remove(provider_name)
            self.action_providers = tuple(ap)

    #
    #   'portal_actions' interface methods
    #
    security.declarePublic('listFilteredActionsFor')

    def listFilteredActionsFor(self, object=None):
        """ List all actions available to the user.
        """
        #cache = None
        #cache_mgr = getToolByName(self, 'portal_actionscache', None)

        #if cache_mgr is not None:
        #    cache = cache_mgr.ZCacheManager_getCache()

        #if cache is not None:
        #    pm = getToolByName(self, 'portal_membership')
        #    if object is None:
        #        object_url = ''
        #    else:
        #        object_url = object.absolute_url()
        #    if pm.isAnonymousUser():
        #        member = None
        #    else:
        #        member = pm.getAuthenticatedMember()
        #    # Prepare a cache key.
        #    keyset = {'object_url': object_url,
        #              'member': member,
        #             }
        #    result = cache.ZCache_get(ob=self, keywords=keyset)
        #    if result is not None:
        #        # Got a cached value.
        #        return result

        actions = []
        ec = getExprContext(self, object)

        # Include actions from specific tools.
        for provider_name in self.listActionProviders():
            provider = getattr(self, provider_name)
            if IActionProvider.isImplementedBy(provider):
                start = time()
                actions.extend(provider.listActionInfos(object=object, ec=ec))
                stop = time()
                open('/tmp/provider_times',
                     'a').write('%-20s: %8.3f\n' % (provider_name,
                                                    (stop - start) * 1000))
            else:
                # for Action Providers written for CMF versions before 1.5
                actions.extend(self._listActionInfos(provider, object))

        # Include actions from object.
        if object is not None:
            base = aq_base(object)
            if IActionProvider.isImplementedBy(base):
                actions.extend(object.listActionInfos(object=object))
            elif hasattr(base, 'listActions'):
                # for objects written for CMF versions before 1.5
                actions.extend(self._listActionInfos(object, object))

        # Reorganize the actions by category.
        filtered_actions = {
            'user': [],
            'folder': [],
            'object': [],
            'global': [],
            'workflow': [],
        }

        for action in actions:
            catlist = filtered_actions.setdefault(action['category'], [])
            catlist.append(action)

        #if cache is not None:
        #    result = cache.ZCache_set(ob=self, data=filtered_actions,
        #                              keywords=keyset)
        return filtered_actions

    # listFilteredActions() is an alias.
    security.declarePublic('listFilteredActions')
    listFilteredActions = listFilteredActionsFor

    security.declarePrivate('ZCacheable_getModTime')

    def ZCacheable_getModTime(self, mtime_func=None):
        '''Returns the highest of the last mod times.'''
        # Based on:
        #   mtime_func
        #   self.mtime
        #   self.__class__.mtime
        #   (if in a ZClass) zclass_instance.mtime
        #                    zclass_instance.__class__.mtime
        mtime = mtime_func and mtime_func() or 0
        base = aq_base(self)
        return max(getattr(base, '_p_mtime', mtime), mtime)

    #
    #   Helper method for backwards compatibility
    #
    def _listActionInfos(self, provider, object):
        """ for Action Providers written for CMF versions before 1.5
        """
        warn(
            'ActionProvider interface not up to date. In CMF 1.6 '
            'portal_actions will ignore listActions() of \'%s\'.' %
            provider.getId(), DeprecationWarning)
        info = getOAI(self, object)
        actions = provider.listActions(info)

        action_infos = []
        if actions and not isinstance(actions[0], dict):
            ec = getExprContext(self, object)
            for ai in actions:
                if not ai.getVisibility():
                    continue
                permissions = ai.getPermissions()
                if permissions:
                    category = ai.getCategory()
                    if (object is not None
                            and (category.startswith('object')
                                 or category.startswith('workflow'))):
                        context = object
                    elif (info['folder'] is not None
                          and category.startswith('folder')):
                        context = info['folder']
                    else:
                        context = info['portal']
                    for permission in permissions:
                        allowed = _checkPermission(permission, context)
                        if allowed:
                            break
                    if not allowed:
                        continue
                if not ai.testCondition(ec):
                    continue
                action_infos.append(ai.getAction(ec))
        else:
            for i in actions:
                if not i.get('visible', 1):
                    continue
                permissions = i.get('permissions', None)
                if permissions:
                    category = i['category']
                    if (object is not None
                            and (category.startswith('object')
                                 or category.startswith('workflow'))):
                        context = object
                    elif (info['folder'] is not None
                          and category.startswith('folder')):
                        context = info['folder']
                    else:
                        context = info['portal']

                    for permission in permissions:
                        allowed = _checkPermission(permission, context)
                        if allowed:
                            break
                    if not allowed:
                        continue
                action_infos.append(i)
        return action_infos
Example #15
0
class ActionsTool(UniqueObject, Folder, ActionProviderBase):
    """
        Weave together the various sources of "actions" which are apropos
        to the current user and context.
    """

    __implements__ = (IActionsTool, ActionProviderBase.__implements__)

    id = 'portal_actions'
    meta_type = 'CMF Actions Tool'
    _actions = (ActionInformation(
        id='folderContents',
        title='Folder contents',
        action=Expression(text='string:${folder_url}/folder_contents'),
        condition=Expression(text='python: folder is not object'),
        permissions=(ListFolderContents, ),
        category='folder',
        visible=1), )

    action_providers = ('portal_membership', 'portal_actions',
                        'portal_registration', 'portal_types',
                        'portal_discussion', 'portal_undo',
                        'portal_syndication', 'portal_workflow',
                        'portal_properties')

    security = ClassSecurityInfo()

    manage_options = (ActionProviderBase.manage_options +
                      ({
                          'label': 'Action Providers',
                          'action': 'manage_actionProviders'
                      }, {
                          'label': 'Overview',
                          'action': 'manage_overview'
                      }) + Folder.manage_options)

    #
    #   ZMI methods
    #
    security.declareProtected(ManagePortal, 'manage_overview')
    manage_overview = DTMLFile('explainActionsTool', _dtmldir)
    manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir)

    security.declareProtected(ManagePortal, 'manage_aproviders')

    def manage_aproviders(self,
                          apname='',
                          chosen=(),
                          add_provider=0,
                          del_provider=0,
                          REQUEST=None):
        """
        Manage action providers through-the-web.
        """
        providers = list(self.listActionProviders())
        new_providers = []
        if add_provider:
            providers.append(apname)
        elif del_provider:
            for item in providers:
                if item not in chosen:
                    new_providers.append(item)
            providers = new_providers
        self.action_providers = tuple(providers)
        if REQUEST is not None:
            return self.manage_actionProviders(
                self, REQUEST, manage_tabs_message='Providers changed.')

    #
    #   Programmatically manipulate the list of action providers
    #
    security.declareProtected(ManagePortal, 'listActionProviders')

    def listActionProviders(self):
        """ List the ids of all Action Providers queried by this tool.
        """
        return self.action_providers

    security.declareProtected(ManagePortal, 'addActionProvider')

    def addActionProvider(self, provider_name):
        """ Add an Action Provider id to the providers queried by this tool.
        """
        ap = list(self.action_providers)
        if hasattr(self, provider_name) and provider_name not in ap:
            ap.append(provider_name)
            self.action_providers = tuple(ap)

    security.declareProtected(ManagePortal, 'deleteActionProvider')

    def deleteActionProvider(self, provider_name):
        """ Delete an Action Provider id from providers queried by this tool.
        """
        ap = list(self.action_providers)
        if provider_name in ap:
            ap.remove(provider_name)
            self.action_providers = tuple(ap)

    #
    #   'portal_actions' interface methods
    #
    security.declarePublic('listFilteredActionsFor')

    def listFilteredActionsFor(self, object=None):
        """ List all actions available to the user.
        """
        actions = []

        # Include actions from specific tools.
        for provider_name in self.listActionProviders():
            provider = getattr(self, provider_name)
            if IActionProvider.isImplementedBy(provider):
                actions.extend(provider.listActionInfos(object=object))

        # Include actions from object.
        if object is not None:
            if IActionProvider.isImplementedBy(object):
                actions.extend(object.listActionInfos(object=object))

        # Reorganize the actions by category.
        filtered_actions = {
            'user': [],
            'folder': [],
            'object': [],
            'global': [],
            'workflow': [],
        }
        for action in actions:
            category = action['category']
            catlist = filtered_actions.get(category, None)
            if catlist is None:
                filtered_actions[category] = catlist = []
            catlist.append(action)
            # ...should you need it, here's some code that filters
            # by equality (use instead of the line above)
            #if not action in catlist:
            #    catlist.append(action)
        return filtered_actions

    # listFilteredActions() is an alias.
    security.declarePublic('listFilteredActions')
    listFilteredActions = listFilteredActionsFor