Exemplo n.º 1
0
    def TreatingGroupsWithDeactivatedVocabulary__call__(self, context):
        active_orgs = get_organizations(only_selected=True)
        not_active_orgs = [
            org for org in get_organizations(only_selected=False)
            if org not in active_orgs
        ]
        res_active = []
        for active_org in active_orgs:
            org_uid = active_org.UID()
            res_active.append(
                SimpleTerm(
                    org_uid, org_uid,
                    safe_unicode(active_org.get_full_title(first_index=1))))
        res = humansorted(res_active, key=attrgetter('title'))

        res_not_active = []
        for not_active_org in not_active_orgs:
            org_uid = not_active_org.UID()
            res_not_active.append(
                SimpleTerm(
                    org_uid, org_uid,
                    _tr('${element_title} (Inactive)',
                        mapping={
                            'element_title':
                            safe_unicode(
                                not_active_org.get_full_title(first_index=1))
                        })))
        res = res + humansorted(res_not_active, key=attrgetter('title'))
        return SimpleVocabulary(res)
Exemplo n.º 2
0
 def validate(self, value):
     selected_org_uids = get_organizations(only_selected=True,
                                           the_objects=False)
     removed_orgs_uids = set(selected_org_uids).difference(value)
     # check that removed orgs are not used as groups_in_charge of an organization
     orgs = get_organizations(only_selected=False, the_objects=True)
     for org in orgs:
         if removed_orgs_uids.intersection(org.groups_in_charge):
             msgid = "can_not_unselect_plone_group_org"
             msg = _(msgid, mapping={'org_url': org.absolute_url()})
             raise Invalid(msg)
Exemplo n.º 3
0
 def test_get_organizations_follows_selected_organizations_order(self):
     self.assertEqual(get_organizations(only_selected=True), [self.dep1])
     select_organization(self.dep2.UID())
     self.assertEqual(get_organizations(only_selected=True, caching=False),
                      [self.dep1, self.dep2])
     select_organization(self.dep1.UID(), remove=True)
     select_organization(self.dep2.UID(), remove=True)
     select_organization(self.dep2.UID())
     select_organization(self.dep1.UID())
     self.assertEqual(get_organizations(only_selected=True, caching=False),
                      [self.dep2, self.dep1])
Exemplo n.º 4
0
    def _setupForOrgs(self, number_of_orgs):
        self.changeUser('admin')
        cfg = self.meetingConfig
        cfg2 = self.meetingConfig2
        # remove existing groups and add our own
        # make what necessary for groups to be removable...
        cfg.setOrderedGroupsInCharge(())
        cfg.setSelectableCopyGroups(())
        cfg.setSelectableAdvisers(())
        cfg2.setOrderedGroupsInCharge(())
        cfg2.setSelectableCopyGroups(())
        cfg2.setSelectableAdvisers(())
        orgs = get_organizations(only_selected=True)
        for org in orgs:
            self._select_organization(org.UID(), remove=True)
            for ploneGroup in get_plone_groups(org.UID()):
                for memberId in ploneGroup.getGroupMemberIds():
                    ploneGroup.removeMember(memberId)
        # remove items defined in the tool
        self._removeConfigObjectsFor(cfg, folders=['recurringitems', 'itemtemplates', 'categories'])
        self._removeConfigObjectsFor(cfg2, folders=['recurringitems', 'itemtemplates', 'categories'])

        # remove groups
        self._removeOrganizations()
        # create groups
        for i in range(number_of_orgs):
            org = self.create('organization', id=i, title='Org %d' % i)
            self._select_organization(org.UID())
Exemplo n.º 5
0
 def test_get_organizations_kept_org_uids(self):
     self.assertEqual(get_organizations(), [self.dep1])
     self.assertEqual(
         get_organizations(kept_org_uids=['some_unexisting_uid']), [])
     self.assertEqual(get_organizations(kept_org_uids=[self.dep1.UID()]),
                      [self.dep1])
     self.assertEqual(
         get_organizations(
             kept_org_uids=['some_unexisting_uid',
                            self.dep1.UID()]), [self.dep1])
     # make sure order is preserved
     self.assertEqual(
         get_organizations(only_selected=False,
                           kept_org_uids=[self.dep2.UID(),
                                          self.dep1.UID()]),
         [self.dep2, self.dep1])
Exemplo n.º 6
0
    def _turn_ids_into_uids(self, data):
        org_uids = get_organizations(only_selected=False, the_objects=False)

        def _get_org_uid(field_name, field_value):
            """Get org UID as given field_value may be an UID or an id."""

            if field_value in org_uids:
                return field_value
            else:
                org_uid = org_id_to_uid(field_value, raise_on_error=False)
                if org_uid is None:
                    raise BadRequest(ORG_FIELD_VALUE_ERROR %
                                     (field_value, field_name))
                return org_uid

        for field_name in self._turn_ids_into_uids_fieldnames:
            field_value = data.get(field_name)
            if field_value:
                if hasattr(field_value, "__iter__"):
                    data[field_name] = []
                    for v in field_value:
                        data[field_name].append(_get_org_uid(field_name, v))
                else:
                    data[field_name] = _get_org_uid(field_name, field_value)
        return data
Exemplo n.º 7
0
    def get_order(self, associated_org_uids=[], cfg=None):
        '''Returns organization position among every selected organizations.
           If p_associated_org_uids is given, returns the order of the lowest org position.
           In this case, p_cfg must be given.'''
        def _get_index(orgs, org):
            """Return position of org among orgs, return 0 if org not found (not selected),
               it it like if it was using the first organization."""
            try:
                # +1 to index as index 0 is for no more selected organizations
                index = orgs.index(org) + 1
            except ValueError:
                index = 0
            return index

        org_uids = get_organizations(only_selected=True, the_objects=False)
        i = _get_index(org_uids, self.UID())
        # if we received associated_org_uids we must consider associated group
        # that has the lowest position
        if associated_org_uids:
            # if we have MeetingConfig.orderedAssociatedOrganizations, we use it
            # either we use organizations selected in plonegroup
            org_uids = cfg.getOrderedAssociatedOrganizations() or org_uids
            # orgs are sorted so, the first we find, we return it
            for org_uid in org_uids:
                if org_uid in associated_org_uids:
                    # we found the associated org with lowest position, now check
                    # that the lowest position of this associated group is lower or not
                    # than the position of the proposing group
                    associated_org_index = _get_index(org_uids, org_uid)
                    if associated_org_index < i:
                        i = associated_org_index
                    break
        return i
Exemplo n.º 8
0
    def getPoliceGroups(self):
        orgs = get_organizations()
        res = []
        for org in orgs:
            if org.getId().startswith(POLICE_GROUP_PREFIX):
                res.append(org.getId())

        return res
Exemplo n.º 9
0
 def listGrpBudgetInfosAdviser(self):
     """Returns a list of groups that can be selected on an item to modify budgetInfos field.
     acronym group start with DGF"""
     res = []
     res.append(('', self.utranslate('make_a_choice',
                                     domain='PloneMeeting')))
     orgs = get_organizations(not_empty_suffix='budgetimpactreviewers')
     for group in orgs:
         res.append((group.id, group.getProperty('title')))
     return DisplayList(tuple(res))
Exemplo n.º 10
0
 def getDptForItem(selg, groupid):
     # return department
     res = ''
     groups = get_organizations()
     for group in groups:
         acronym = group.get_acronym()
         if acronym.find('-') < 0:
             res = group.id
         if group.id == groupid:
             break
     return res
Exemplo n.º 11
0
    def _migrateItemsWorkflowHistory(self):
        """Migrate items workflow_history and remap states."""
        # as state "proposed_to_finance" changed to "proposed_to_finance_waiting_advices",
        # we must update various places
        # organizations
        old_finance_value = 'meeting-config-college__state__proposed_to_finance'
        new_finance_value = 'meeting-config-college__state__proposed_to_finance_waiting_advices'
        for org in get_organizations():
            for field_name in ('item_advice_states', 'item_advice_edit_states',
                               'item_advice_view_states'):
                value = getattr(org, field_name) or []
                if old_finance_value in value:
                    setattr(
                        org, field_name,
                        tuple(
                            replace_in_list(value, old_finance_value,
                                            new_finance_value)))
        # MeetingConfigs
        old_finance_value = 'proposed_to_finance'
        new_finance_value = 'proposed_to_finance_waiting_advices'
        for cfg in self.tool.objectValues('MeetingConfig'):
            for field_name in ('itemAdviceStates', 'itemAdviceEditStates',
                               'itemAdviceViewStates'):
                value = getattr(cfg, field_name) or []
                if old_finance_value in value:
                    setattr(
                        cfg, field_name,
                        tuple(
                            replace_in_list(value, old_finance_value,
                                            new_finance_value)))

        # update item workflow_history and MeetingConfig fields using states/transitions
        self.updateWFStatesAndTransitions(
            query={
                'portal_type': ('MeetingItemCollege', 'MeetingItemBourgmestre')
            },
            review_state_mappings={
                # meeting-config-college
                'proposed_to_finance': 'proposed_to_finance_waiting_advices'
            },
            transition_mappings={
                # meeting-config-college
                'proposeToFinance': 'wait_advices_from_proposed_to_director',
                'askAdvicesByInternalReviewer':
                'wait_advices_from_proposed_to_internal_reviewer',
                'askAdvicesByItemCreator': 'wait_advices_from_itemcreated',
                # meeting-config-bourgmestre
                'askAdvicesByDirector':
                'wait_advices_from_proposed_to_director',
            },
            # will be done by next step in migration
            update_local_roles=False)
Exemplo n.º 12
0
    def ActiveCreatingGroupVocabulary__call__(self, context):
        terms = []
        factory = getUtility(
            IVocabularyFactory,
            'collective.contact.plonegroup.organization_services')
        vocab = factory(context)

        # we get all orgs where there are plone groups with the creating group suffix and with users
        to_keep = set(
            get_organizations(not_empty_suffix=CREATING_GROUP_SUFFIX,
                              only_selected=False,
                              the_objects=False,
                              caching=False))
        to_keep |= set(
            get_organizations(not_empty_suffix=CONTACTS_PART_SUFFIX,
                              only_selected=False,
                              the_objects=False,
                              caching=False))
        for term in vocab:
            if term.value in to_keep:
                terms.append(term)
        return SimpleVocabulary(terms)
Exemplo n.º 13
0
 def getDptPos(self, groupid):
     # return department position in active groups list
     res = ''
     groups = get_organizations()
     cpt_dpt = 0
     for group in groups:
         acronym = group.get_acronym()
         if acronym.find('-') < 0:
             cpt_dpt = cpt_dpt + 1
         if group.id == groupid:
             break
     res = cpt_dpt
     return res
Exemplo n.º 14
0
 def test_get_organizations(self):
     # only_selected
     self.assertEqual(get_organizations(only_selected=True), [self.dep1])
     self.assertEqual(get_organizations(only_selected=False),
                      [self.dep1, self.dep2])
     # the_objects
     self.assertEqual(get_organizations(the_objects=True), [self.dep1])
     self.assertEqual(get_organizations(the_objects=False), [self.uid])
     # not_empty_suffix
     self.assertEqual(get_organizations(not_empty_suffix=None), [self.dep1])
     self.assertEqual(get_organizations(not_empty_suffix=u'director'),
                      [self.dep1])
     self.assertEqual(get_organizations(not_empty_suffix=u'observer'), [])
Exemplo n.º 15
0
def set_creating_group(self, types='', uid='', change='', force=''):
    """Set creating_group for existing objects."""
    if not check_zope_admin():
        return "You must be a zope manager to run this script"
    if not uid or not types:
        return 'You have to pass types (comma separated) and uid parameters'
    out = []
    ptypes = [typ.strip() for typ in types.split(',')]
    # TODO check if each ptype exists
    # TODO check if creating_group is in schema
    uids = get_organizations(not_empty_suffix=CREATING_GROUP_SUFFIX,
                             only_selected=False,
                             the_objects=False,
                             caching=False)
    uids += get_organizations(not_empty_suffix=CONTACTS_PART_SUFFIX,
                              only_selected=False,
                              the_objects=False,
                              caching=False)
    uid = safe_unicode(uid)
    if uid not in uids:
        return "You cannot set this uid '{}' not in configured uids '{}'".format(
            uid, uids)
    # search
    pc = self.portal_catalog
    brains = pc(portal_type=ptypes)
    out.append('Found {} objects of types {}'.format(len(brains), ptypes))
    modified = 0
    if change == '1':
        for brain in brains:
            obj = brain.getObject()
            if force == '1' or obj.creating_group is None:
                modified += 1
                obj.creating_group = uid
                obj.reindexObject(['assigned_group'])
    out.append('Modified {} objects'.format(modified))
    return '\n'.join(out)
Exemplo n.º 16
0
def export_orgs(self):
    """
      Export the existing organizations informations as a dictionnary
    """
    member = api.user.get_current()
    if not member.has_role('Manager'):
        raise Unauthorized('You must be a Manager to access this script !')

    if not hasattr(self, 'portal_plonemeeting'):
        return "PloneMeeting must be installed to run this script !"

    data = {}
    for org in get_organizations(only_selected=False):
        data[org.getId()] = (org.Title(), org.Description(), org.get_acronym())
    return data
Exemplo n.º 17
0
 def orderedOrgs(self):
     """Display organizations if one of the selected inserting methods relies on organizations.
        Returns a list of tuples, with organization title as first element and
        goupsInCharge organizations titles as second element."""
     res = []
     orgs_inserting_methods = [
         method['insertingMethod']
         for method in self.cfg.getInsertingMethodsOnAddItem()
         if 'organization' in self.inserting_methods_fields_mapping[
             method['insertingMethod']]
     ]
     if orgs_inserting_methods:
         orgs = get_organizations(only_selected=True)
         res = [(org.Title(), ', '.join([
             gic.Title()
             for gic in org.get_groups_in_charge(the_objects=True)
         ] or '')) for org in orgs]
     return res
   def test_ws_showCategories(self):
       """
         Test while getting configInfos with categories.
       """
       self.changeUser('pmCreator1')
       req = getConfigInfosRequest()
       req._showCategories = True
       # Serialize the request so it can be easily tested
       responseHolder = getConfigInfosResponse()
       response = SOAPView(self.portal,
                           req).getConfigInfosRequest(req, responseHolder)
       resp = deserialize(response)
       expected = """<ns1:getConfigInfosResponse xmlns:ns1="http://ws4pm.imio.be" """ \
                  """xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" """ \
                  """xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" """ \
                  """xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" """ \
                  """xmlns:xsd="http://www.w3.org/2001/XMLSchema" """ \
                  """xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">"""
       # _configInfo
       for cfg in self.tool.getActiveConfigs():
           expected += """
 <configInfo xsi:type="ns1:ConfigInfo">
   <UID>%s</UID>
   <id>%s</id>
   <title>%s</title>
   <description>%s</description>%s%s
 </configInfo>""" % (cfg.UID(), cfg.getId(), cfg.Title(), cfg.Description(),
                     self._getItemPositiveDecidedStatesFromConfig(cfg),
                     self._getResultCategoriesForConfig(cfg))
       # _groupInfo
       for grp in get_organizations():
           expected += """
 <groupInfo xsi:type="ns1:GroupInfo">
   <UID>%s</UID>
   <id>%s</id>
   <title>%s</title>
   <description>%s</description>
 </groupInfo>""" % (grp.UID(), grp.getId(), grp.Title(), grp.Description())
       # footer.  Empty description is represented like <description/>
       expected = expected.replace('<description></description>', '<description/>') \
           + "\n</ns1:getConfigInfosResponse>\n"
       self.assertEquals(expected, resp)
       # the category 'subproducts' is only available to vendors
       self.assertFalse('<id>subproducts</id>' in resp)
Exemplo n.º 19
0
 def getServicePos(self, group, meeting=None, late=False):
     # return service position in active groups list incremented by item for department
     groupid = group.id
     cpt_srv = 0
     groups = get_organizations()
     for gr in groups:
         acronym = gr.get_acronym()
         if acronym.find('-') >= 0:
             # only increment if no empty service and not current group
             if (gr.id != groupid) and (not self.getServiceIsEmpty(
                     gr.id, meeting, late)):
                 cpt_srv = cpt_srv + 1
         else:  # new department, reset numbering
             cpt_srv = 1
         if gr.id == groupid:
             break
     dptid = self.getDptForItem(group.id)
     cpt_srv = cpt_srv + self.getCountDptItems(meeting, dptid, late)
     return cpt_srv
Exemplo n.º 20
0
def set_default_in_charge_if_misssing_and_fix_certified_sign(
        default_in_charge_uid,
        remove_certified_signatures=[],
        remove_certified_signatures_ignore_pattern=None):
    cfg_groups = get_organizations(only_selected=False)
    for group in cfg_groups:
        if not group.groups_in_charge:
            group.groups_in_charge = [default_in_charge_uid]
            logger.info(u"Added default group in charge to {}".format(
                group.title))

        if not remove_certified_signatures_ignore_pattern or not re.match(
                remove_certified_signatures_ignore_pattern, group.title):
            # the organisation members create items
            certified_signatures = []
            for signature in group.certified_signatures:
                if signature.get(
                        'signature_number') not in remove_certified_signatures:
                    certified_signatures.append(signature)

            group.certified_signatures = certified_signatures
        group.reindexObject()
Exemplo n.º 21
0
    def test_pm_PloneGroupSettingsOrganizationsValidator(self):
        """Can not unselected an organization if used as groups_in_charge
           of another organziations."""

        self.changeUser('siteadmin')
        validator = PloneGroupSettingsOrganizationsValidator(
            self.portal, self.request, None,
            IContactPlonegroupConfig['organizations'], None)
        organizations = get_registry_organizations()
        self.assertIsNone(validator.validate(organizations))

        # org can not be unselected if used in another org.groups_in_charge
        orgs = get_organizations()
        orgs[0].groups_in_charge = [orgs[1].UID()]
        with self.assertRaises(Invalid) as cm:
            validator.validate([organizations[0]])
        validation_error_msg = _('can_not_unselect_plone_group_org',
                                 mapping={'item_url': orgs[0].absolute_url()})
        self.assertEqual(cm.exception.message, validation_error_msg)
        # but other could be unselected
        self.assertIsNone(validator.validate([organizations[1]]))
        # remove groups_in_charge so org may be unselected
        orgs[0].groups_in_charge = []
        self.assertIsNone(validator.validate([organizations[0]]))
Exemplo n.º 22
0
    def run(self):
        self.data = self.profileData
        if not self.data:
            return self.noDataMessage
        # Register classes again, after model adaptations have been performed
        # (see comment in __init__.py)
        registerClasses()
        # if we already have existing organizations, we do not add additional ones
        own_org = get_own_organization()
        alreadyHaveGroups = bool(own_org.objectValues())
        savedMeetingConfigsToCloneTo = {}
        savedOrgsData = {}
        if not alreadyHaveGroups or self.data.forceAddUsersAndGroups:
            # 1) create organizations so we have org UIDS to initialize 'fct_orgs'
            orgs, active_orgs, savedOrgsData = self.addOrgs(self.data.orgs)
            # 2) create plonegroup functions (suffixes) to create Plone groups
            functions = get_registry_functions()
            function_ids = [function['fct_id'] for function in functions]
            # append new functions
            suffixes = MEETING_GROUP_SUFFIXES + EXTRA_GROUP_SUFFIXES
            for suffix in suffixes:
                if suffix['fct_id'] not in function_ids:
                    copied_suffix = suffix.copy()
                    copied_suffix['fct_title'] = translate(
                        suffix['fct_title'],
                        domain='PloneMeeting',
                        context=self.request)
                    # if org_path not found, do not fail but log, it is often the case in tests
                    # in which we do not add additional organizations because it breaks some tests
                    copied_suffix['fct_orgs'] = []
                    for org_path in suffix['fct_orgs']:
                        try:
                            fct_org = own_org.restrictedTraverse(org_path)
                        except KeyError:
                            logger.warning(
                                "Could not find an organization with path {0} "
                                "while setting 'fct_orgs' for {1}".format(
                                    org_path, suffix['fct_id']))
                            continue
                        copied_suffix['fct_orgs'].append(fct_org.UID())
                    functions.append(copied_suffix)
            # 3) manage organizations, set every organizations so every Plone groups are created
            # then disable orgs that are not active
            invalidate_soev_cache()
            invalidate_ssoev_cache()
            already_active_orgs = get_registry_organizations()
            org_uids = [
                org_uid for org_uid in get_organizations(only_selected=False,
                                                         the_objects=False)
                if org_uid not in already_active_orgs
            ]
            set_registry_organizations(org_uids)
            set_registry_functions(functions)
            active_org_uids = [org.UID() for org in active_orgs]
            set_registry_organizations(already_active_orgs + active_org_uids)
            # 4) add users to Plone groups
            self.addUsers(self.data.orgs)
            # 5) now that organizations are created, we add persons and held_positions
            self.addPersonsAndHeldPositions(self.data.persons,
                                            source=self.profilePath)

        created_cfgs = []
        for mConfig in self.data.meetingConfigs:
            # XXX we need to defer the management of the 'meetingConfigsToCloneTo'
            # defined on the mConfig after the creation of every mConfigs because
            # if we defined in mConfig1.meetingConfigsToCloneTo the mConfig2 id,
            # it will try to getattr this meetingConfig2 id that does not exist yet...
            # so save defined values, removed them from mConfig and manage that after
            savedMeetingConfigsToCloneTo[
                mConfig.id] = mConfig.meetingConfigsToCloneTo
            mConfig.meetingConfigsToCloneTo = []
            cfg = self.createMeetingConfig(mConfig, source=self.profilePath)
            if cfg:
                created_cfgs.append(cfg)
                self._finishConfigFor(cfg, data=mConfig)

        # manage other_mc_correspondences
        for created_cfg in created_cfgs:
            self._manageOtherMCCorrespondences(created_cfg)

        # now that every meetingConfigs have been created, we can manage the meetingConfigsToCloneTo
        # and orgs advice states related fields
        for mConfigId in savedMeetingConfigsToCloneTo:
            if not savedMeetingConfigsToCloneTo[mConfigId]:
                continue
            # initialize the attribute on the meetingConfig and call _updateCloneToOtherMCActions
            cfg = getattr(self.tool, mConfigId)
            # validate the MeetingConfig.meetingConfigsToCloneTo data that we are about to set
            # first replace cfg1 and cfg2 by corresponding cfg id
            adapted_cfgsToCloneTo = deepcopy(
                savedMeetingConfigsToCloneTo[mConfigId])
            for cfgToCloneTo in adapted_cfgsToCloneTo:
                cfgToCloneTo['meeting_config'] = self.cfg_num_to_id(
                    cfgToCloneTo['meeting_config'])
            error = cfg.validate_meetingConfigsToCloneTo(adapted_cfgsToCloneTo)
            if error:
                raise PloneMeetingError(MEETING_CONFIG_ERROR %
                                        (cfg.Title(), cfg.getId(), error))
            cfg.setMeetingConfigsToCloneTo(adapted_cfgsToCloneTo)
            cfg._updateCloneToOtherMCActions()
        for org_uid, values in savedOrgsData.items():
            org = uuidToObject(org_uid, unrestricted=True)
            # turn cfg1__state__itemcreated into meeting-config-id__state__itemcreated
            org.item_advice_states = self._correct_advice_states(
                values['item_advice_states'])
            org.item_advice_edit_states = self._correct_advice_states(
                values['item_advice_edit_states'])
            org.item_advice_view_states = self._correct_advice_states(
                values['item_advice_view_states'])
            org.groups_in_charge = [
                org_id_to_uid(group_id)
                for group_id in values['groups_in_charge']
            ]

        # finally, create the current user (admin) member area
        self.portal.portal_membership.createMemberArea()
        # at the end, add users outside PloneMeeting groups because
        # they could have to be added in groups created by the MeetingConfig
        if not alreadyHaveGroups:
            # adapt userDescr.ploneGroups to turn cfg_num into cfg_id
            self.addUsersOutsideGroups(self.data.usersOutsideGroups)

        # commit before continuing so elements like scales on annex types are correctly saved
        transaction.commit()
        return self.successMessage
Exemplo n.º 23
0
    def validate(self, value):
        # check that if a suffix is removed, it is not used in MeetingConfig or MeetingItems
        stored_suffixes = get_all_suffixes(only_enabled=True)
        # get removed suffixes...
        saved_suffixes = [func['fct_id'] for func in value]
        saved_enabled_suffixes = [
            func['fct_id'] for func in value if func['enabled']
        ]
        removed_suffixes = list(
            set(stored_suffixes) - set(saved_enabled_suffixes))
        really_removed_suffixes = list(
            set(stored_suffixes) - set(saved_suffixes))
        org_uids = get_organizations(only_selected=False, the_objects=False)
        removed_plonegroups = [
            get_plone_group_id(org_uid, removed_suffix) for org_uid in org_uids
            for removed_suffix in removed_suffixes
        ]
        # ... and new defined fct_orgs as it will remove some suffixed groups
        stored_functions = get_registry_functions()
        old_functions = {
            dic['fct_id']: {
                'fct_title': dic['fct_title'],
                'fct_orgs': dic['fct_orgs'],
                'enabled': dic['enabled']
            }
            for dic in stored_functions
        }
        new_functions = {
            dic['fct_id']: {
                'fct_title': dic['fct_title'],
                'fct_orgs': dic['fct_orgs'],
                'enabled': dic['enabled']
            }
            for dic in value
        }
        for new_function, new_function_infos in new_functions.items():
            if new_function_infos['fct_orgs'] and \
               old_functions[new_function]['fct_orgs'] != new_function_infos['fct_orgs']:
                # check that Plone group is empty for not selected fct_orgs
                for org_uid in org_uids:
                    if org_uid in new_function_infos['fct_orgs']:
                        continue
                    removed_plonegroups.append(
                        get_plone_group_id(org_uid, new_function))
            elif new_function_infos['enabled'] is False:
                # check that Plone groups are all empty
                for org_uid in org_uids:
                    removed_plonegroups.append(
                        get_plone_group_id(org_uid, new_function))

        # check that plonegroups and suffixes not used in MeetingConfigs
        removed_plonegroups = set(removed_plonegroups)
        tool = api.portal.get_tool('portal_plonemeeting')
        # advisers
        advisers_removed_plonegroups = [
            REAL_ORG_UID_PATTERN.format(removed_plonegroup_id.split('_')[0])
            for removed_plonegroup_id in removed_plonegroups
            if removed_plonegroup_id.endswith('_advisers')
        ]
        for cfg in tool.objectValues('MeetingConfig'):
            msg = _("can_not_delete_plone_group_meetingconfig",
                    mapping={'cfg_title': safe_unicode(cfg.Title())})
            # copyGroups
            if removed_plonegroups.intersection(cfg.getSelectableCopyGroups()):
                raise Invalid(msg)
            # advisers (selectableAdvisers/selectableAdviserUsers)
            if set(advisers_removed_plonegroups).intersection(cfg.getSelectableAdvisers()) or \
               set(advisers_removed_plonegroups).intersection(cfg.getSelectableAdviserUsers()):
                raise Invalid(msg)
            # suffixes, values are like 'suffix_proposing_group_level1reviewers'
            composed_values_attributes = [
                'itemAnnexConfidentialVisibleFor',
                'adviceAnnexConfidentialVisibleFor',
                'meetingAnnexConfidentialVisibleFor',
                'itemInternalNotesEditableBy'
            ]
            for composed_values_attr in composed_values_attributes:
                values = cfg.getField(composed_values_attr).getAccessor(cfg)()
                values = [
                    v for v in values for r in removed_suffixes if r in v
                ]
                if values:
                    raise Invalid(msg)
            # itemWFValidationLevels, may be disabled if validation level also disabled
            # but not removed
            item_enabled_val_suffixes = get_item_validation_wf_suffixes(cfg)
            if set(really_removed_suffixes).intersection(
                    item_enabled_val_suffixes):
                raise Invalid(msg)
            all_item_val_suffixes = get_item_validation_wf_suffixes(
                cfg, only_enabled=False)
            if set(removed_suffixes).intersection(all_item_val_suffixes):
                raise Invalid(msg)
        # check that plone_group not used in MeetingItems
        # need to be performant or may kill the instance when several items exist
        if removed_plonegroups:
            catalog = api.portal.get_tool('portal_catalog')
            # copy_groups
            brains = catalog.unrestrictedSearchResults(
                meta_type="MeetingItem",
                getCopyGroups=tuple(removed_plonegroups))
            if not brains:
                brains = catalog.unrestrictedSearchResults(
                    meta_type="MeetingItem",
                    indexAdvisers=tuple(advisers_removed_plonegroups))
            for brain in brains:
                item = brain.getObject()
                if item.isDefinedInTool():
                    msgid = "can_not_delete_plone_group_config_meetingitem"
                else:
                    msgid = "can_not_delete_plone_group_meetingitem"
                msg = _(msgid, mapping={'item_url': item.absolute_url()})
                raise Invalid(msg)
Exemplo n.º 24
0
    def run(self):
        member = self.portal.portal_membership.getAuthenticatedMember()
        if not member.has_role("Manager"):
            raise ValueError("You must be a Manager to access this script !")

        # Load all csv into memory
        cfg_groups = get_organizations(only_selected=False)
        for group in cfg_groups:
            self.grp_id_mapping[group.UID()] = group

        logger.info("Load {0}".format(self.f_group_mapping))
        with io.open(self.f_group_mapping, "r") as csvfile:
            reader = csv.reader(csvfile)
            for row in reader:
                grp_id = row[1].strip()
                if grp_id in self.grp_id_mapping:
                    self.groups[
                        row[0].strip()] = self.grp_id_mapping[grp_id].UID()
                else:
                    self.groups[row[0].strip()] = self.default_group

        meetings = {}
        logger.info("Load {0}".format(self.f_meetings))
        with io.open(self.f_meetings, "r") as csvfile:
            reader = csv.reader(csvfile)
            for row in reader:
                if reader.line_num == 1:
                    # skip header line
                    continue
                # Because numbers are not numbers but unicode chars...
                external_id = int(row[0].strip())
                csv_type = safe_unicode(row[6].strip()).lower()
                if 'col' in csv_type:
                    portal_type = self.college_cfg.getMeetingTypeName()
                elif 'cons' in csv_type:
                    portal_type = self.council_cfg.getMeetingTypeName()
                else:
                    continue

                meeting = CSVMeeting(external_id=external_id,
                                     date=row[1].strip(),
                                     created_on=row[2].strip(),
                                     started_on=row[3].strip(),
                                     ended_on=row[4].strip(),
                                     assembly=safe_unicode(row[5].strip()),
                                     portal_type=portal_type,
                                     annexes_dir=self.meeting_annex_dir_path)

                self.add_meeting_to_dict(meetings, meeting)
        self.load_items(self.f_items, meetings)
        # insert All
        self.disable_recurring_items()
        logger.info("Inserting Objects")
        try:
            for csv_meeting in meetings.values():
                if csv_meeting.portal_type == self.college_cfg.getMeetingTypeName(
                ):
                    self.insert_and_close_meeting(self.college_member_folder,
                                                  csv_meeting)
                elif csv_meeting.portal_type == self.council_cfg.getMeetingTypeName(
                ):
                    self.insert_and_close_meeting(self.council_member_folder,
                                                  csv_meeting)
                else:
                    raise NotImplementedError(
                        u"Not managed meeting type '{}' for meeting id {}".
                        format(csv_meeting.type, meeting.external_id))
        finally:
            tool = api.portal.get_tool('portal_plonemeeting')
            self.re_enable_recurring_items()
            tool.invalidateAllCache()

        return self.meeting_counter, self.item_counter, self.errors
def detectContactPlonegroupChange(event):
    """
        Manage our record changes
    """
    if IRecordModifiedEvent.providedBy(
            event):  # and event.record.interface == IContactPlonegroupConfig:
        changes = False
        # this can be called before plonegroup is installed and registry contains relevant keys
        try:
            registry_orgs = get_registry_organizations()
        except InvalidParameterError:
            registry_orgs = []
        if event.record.fieldName == 'organizations' and registry_orgs:
            old_set = set(event.oldValue)
            new_set = set(event.newValue)
            # we detect a new organization
            add_set = new_set.difference(old_set)
            for orga_uid in add_set:
                orga = uuidToObject(orga_uid)
                for fct_dic in get_registry_functions():
                    enabled = fct_dic['enabled']
                    if enabled is False:
                        continue
                    fct_orgs = fct_dic['fct_orgs']
                    if fct_orgs and orga_uid not in fct_orgs:
                        continue
                    if addOrModifyGroup(orga, fct_dic['fct_id'],
                                        fct_dic['fct_title']):
                        changes = True
            # we detect a removed organization. We dont do anything on exsiting groups
            if old_set.difference(new_set):
                changes = True
        elif event.record.fieldName == 'functions' and registry_orgs:
            old_functions = {
                dic['fct_id']: {
                    'fct_title': dic['fct_title'],
                    'fct_orgs': dic['fct_orgs'],
                    'enabled': dic['enabled']
                }
                for dic in event.oldValue
            }
            old_set = set(old_functions.keys())
            new_functions = {
                dic['fct_id']: {
                    'fct_title': dic['fct_title'],
                    'fct_orgs': dic['fct_orgs'],
                    'enabled': dic['enabled']
                }
                for dic in event.newValue
            }
            new_set = set(new_functions.keys())
            # we detect a new function
            add_set = new_set.difference(old_set)
            for new_id in add_set:
                new_title = new_functions[new_id]['fct_title']
                new_orgs = new_functions[new_id]['fct_orgs']
                enabled = new_functions[new_id]['enabled']
                for orga_uid in registry_orgs:
                    if new_orgs and orga_uid not in new_orgs:
                        continue
                    if enabled is False:
                        continue
                    orga = uuidToObject(orga_uid)
                    if addOrModifyGroup(orga, new_id, new_title):
                        changes = True
            # we detect a removed function
            # We may remove Plone groups as we checked before that every are empty
            removed_set = old_set.difference(new_set)
            for removed_id in removed_set:
                for orga_uid in get_organizations(only_selected=False,
                                                  the_objects=False):
                    plone_group_id = get_plone_group_id(orga_uid, removed_id)
                    plone_group = api.group.get(plone_group_id)
                    if plone_group:
                        api.group.delete(plone_group_id)
                        changes = True
            # we detect existing functions for which 'fct_orgs' changed
            for new_id, new_function_infos in new_functions.items():
                new_title = new_function_infos['fct_title']
                new_orgs = new_function_infos['fct_orgs']
                enabled = new_function_infos['enabled']
                if not new_orgs and enabled is True:
                    # we have to make sure Plone groups are created for every selected organizations
                    for orga_uid in registry_orgs:
                        orga = uuidToObject(orga_uid)
                        if addOrModifyGroup(orga, new_id, new_title):
                            changes = True
                else:
                    # fct_orgs changed, we remove every linked Plone groups
                    # except ones defined in new_orgs
                    for orga_uid in get_organizations(only_selected=False,
                                                      the_objects=False):
                        if enabled is True and orga_uid in new_orgs:
                            # make sure Plone group is created or updated if suffix title changed
                            orga = uuidToObject(orga_uid)
                            if addOrModifyGroup(orga, new_id, new_title):
                                changes = True
                        else:
                            # make sure Plone group is deleted
                            plone_group_id = get_plone_group_id(
                                orga_uid, new_id)
                            plone_group = api.group.get(plone_group_id)
                            if plone_group:
                                api.group.delete(plone_group_id)
                                changes = True

        if changes:
            invalidate_sopgv_cache()
            invalidate_sov_cache()
            invalidate_soev_cache()
            invalidate_ssoev_cache()
    def validateSettings(data):
        if not data.organizations:
            raise Invalid(_(u"You must choose at least one organization !"))
        if len(data.organizations) == 1 and data.organizations[0] is None:
            raise Invalid(
                _(u"You must correct the organization error first !"))
        if not data.functions:
            raise Invalid(_(u"You must define at least one function !"))

        # only able to delete a function (suffix) if every linked Plone groups are empty
        stored_suffixes = get_all_suffixes()
        saved_suffixes = [func['fct_id'] for func in data.functions]
        removed_suffixes = list(set(stored_suffixes) - set(saved_suffixes))
        for removed_suffix in removed_suffixes:
            # check that every organizations including not selected
            # linked suffixed Plone group is empty
            for org_uid in get_organizations(only_selected=False,
                                             the_objects=False):
                plone_group_id = get_plone_group_id(org_uid, removed_suffix)
                plone_group = api.group.get(plone_group_id)
                if plone_group and plone_group.getMemberIds():
                    raise Invalid(
                        _(u"can_not_remove_function_every_plone_groups_not_empty",
                          mapping={
                              'removed_function': removed_suffix,
                              'plone_group_id': plone_group_id
                          }))

        # only able to select orgs for an existing function (suffix) if
        # every linked Plone groups of not selected orgs are empty
        stored_functions = get_registry_functions()
        old_functions = {
            dic['fct_id']: {
                'fct_title': dic['fct_title'],
                'fct_orgs': dic['fct_orgs'],
                'enabled': dic['enabled']
            }
            for dic in stored_functions
        }
        new_functions = {
            dic['fct_id']: {
                'fct_title': dic['fct_title'],
                'fct_orgs': dic['fct_orgs'],
                'enabled': dic['enabled']
            }
            for dic in data.functions
        }
        for new_function, new_function_infos in new_functions.items():
            if new_function_infos['fct_orgs'] and \
               old_functions[new_function]['fct_orgs'] != new_function_infos['fct_orgs']:
                # check that Plone group is empty for not selected fct_orgs
                for org_uid in get_organizations(only_selected=False,
                                                 the_objects=False):
                    if org_uid in new_function_infos['fct_orgs']:
                        continue
                    plone_group_id = get_plone_group_id(org_uid, new_function)
                    plone_group = api.group.get(plone_group_id)
                    # use getGroupMembers to ignore '<not found>' users
                    if plone_group and plone_group.getGroupMembers():
                        raise Invalid(
                            _(u"can_not_select_function_orgs_every_other_plone_groups_not_empty",
                              mapping={
                                  'function': new_function,
                                  'plone_group_id': plone_group_id
                              }))
            elif new_function_infos['enabled'] is False:
                # check that Plone groups are all empty
                for org_uid in get_organizations(only_selected=False,
                                                 the_objects=False):
                    plone_group_id = get_plone_group_id(org_uid, new_function)
                    plone_group = api.group.get(plone_group_id)
                    # use getGroupMembers to ignore '<not found>' users
                    if plone_group and plone_group.getGroupMembers():
                        raise Invalid(
                            _(u"can_not_disable_suffix_plone_groups_not_empty",
                              mapping={
                                  'disabled_function': new_function,
                                  'plone_group_id': plone_group_id
                              }))
Exemplo n.º 27
0
    def test_pm_AskedAdvicesVocabulary(self):
        '''Test the "Products.PloneMeeting.vocabularies.askedadvicesvocabulary"
           vocabulary, especially because it is cached.'''
        self.changeUser('siteadmin')
        cfg = self.meetingConfig
        customAdvisers = [{
            'row_id': 'unique_id_000',
            'org': self.developers_uid,
            'gives_auto_advice_on': '',
            'for_item_created_from': '2012/01/01',
            'delay': '2',
            'delay_label': ''
        }, {
            'row_id': 'unique_id_123',
            'org': self.vendors_uid,
            'gives_auto_advice_on': '',
            'for_item_created_from': '2012/01/01',
            'delay': '5',
            'delay_label': ''
        }, {
            'row_id': 'unique_id_456',
            'org': self.vendors_uid,
            'gives_auto_advice_on': '',
            'for_item_created_from': '2012/01/01',
            'delay': '10',
            'delay_label': ''
        }, {
            'row_id': 'unique_id_789',
            'org': self.vendors_uid,
            'gives_auto_advice_on': '',
            'for_item_created_from': '2012/01/01',
            'delay': '20',
            'delay_label': ''
        }]
        cfg.setCustomAdvisers(customAdvisers)
        pmFolder = self.getMeetingFolder()
        vocab = get_vocab(
            pmFolder,
            "Products.PloneMeeting.vocabularies.askedadvicesvocabulary",
            only_factory=True)
        # we have 4 delay-aware advisers and 2 adviser groups selectable as optional
        delayAdvisers = [
            adviser for adviser in cfg.getCustomAdvisers() if adviser['delay']
        ]
        self.assertEqual(len(delayAdvisers), 4)
        self.assertEqual(len(get_organizations(not_empty_suffix='advisers')),
                         2)
        # once get, it is cached, it includes customAdvisers and MeetingConfig.selectableAdvisers
        self.assertEqual(len(vocab(pmFolder)), 6)

        # if we select a new organization, then the cache is cleaned
        # add an organization
        new_org = self.create('organization',
                              title='New organization',
                              acronym='N.G.')
        new_org_uid = new_org.UID()
        cfg.setSelectableAdvisers(cfg.getSelectableAdvisers() +
                                  (new_org_uid, ))
        # cache was cleaned
        self.assertEqual(len(vocab(pmFolder)), 7)
        # edit an organization
        new_org_term_id = 'real_org_uid__{0}'.format(new_org_uid)
        self.assertEqual(
            vocab(pmFolder).by_token[new_org_term_id].title,
            'New organization (Inactive)')
        new_org.title = u'Modified title'
        notify(ObjectModifiedEvent(new_org))
        # cache was cleaned
        self.assertEqual(
            vocab(pmFolder).by_token[new_org_term_id].title,
            'Modified title (Inactive)')
        # select the organization, cache is cleaned
        self._select_organization(new_org_uid)
        self.assertEqual(
            vocab(pmFolder).by_token[new_org_term_id].title, 'Modified title')
        # remove an organization
        # first need to unselect it
        self._select_organization(new_org_uid, remove=True)
        self.portal.restrictedTraverse('@@delete_givenuid')(new_org_uid)
        # cache was cleaned
        self.assertEqual(len(vocab(pmFolder)), 6)

        # if we add/remove/edit a customAdviser, then the cache is cleaned
        # add a customAdviser
        customAdvisers.append({
            'row_id': 'unique_id_999',
            'org': self.vendors_uid,
            'gives_auto_advice_on': '',
            'for_item_created_from': '2012/01/01',
            'delay': '11',
            'delay_label': 'New delay'
        })
        cfg.setCustomAdvisers(customAdvisers)
        cfg.at_post_edit_script()
        self.assertEqual(len(vocab(pmFolder)), 7)
        self.assertTrue(
            'delay_row_id__unique_id_999' in vocab(pmFolder).by_token)
        # delay is displayed in customAdviser title
        self.assertTrue('11 day(s)' in vocab(
            pmFolder).by_token['delay_row_id__unique_id_999'].title)
        # edit a customAdviser
        customAdvisers[-1]['delay'] = '12'
        cfg.setCustomAdvisers(customAdvisers)
        cfg.at_post_edit_script()
        self.assertTrue('12 day(s)' in vocab(
            pmFolder).by_token['delay_row_id__unique_id_999'].title)
        # remove a customAdviser
        customAdvisers = customAdvisers[:-1]
        cfg.setCustomAdvisers(customAdvisers)
        cfg.at_post_edit_script()
        self.assertEqual(len(vocab(pmFolder)), 6)
        # power advisers are taken into account by the vocabulary
        cfg.setPowerAdvisersGroups([self.endUsers_uid])
        cfg.at_post_edit_script()
        self.assertEqual(len(vocab(pmFolder)), 7)
Exemplo n.º 28
0
        return "PloneMeeting must be installed to run this script !"

    try:
        file = open(fname, "rb")
        reader = csv.DictReader(file)
    except Exception, msg:
        file.close()
        return "Error with file : %s" % msg.value

    out = []

    acl = self.acl_users
    pms = api.portal.get_tool('portal_membership')
    pgr = api.portal.get_tool('portal_groups')
    registration = api.portal.get_tool('portal_registration')
    ORGANIZATIONS = get_organizations()

    for row in reader:
        row_id = normalizeString(row['username'], self)
        # add users if not exist
        if row_id not in [ud['userid'] for ud in acl.searchUsers()]:
            pms.addMember(row_id, row['password'], ('Member', ), [])
            member = pms.getMemberById(row_id)
            properties = {'fullname': row['fullname'], 'email': row['email']}
            failMessage = registration.testPropertiesValidity(
                properties, member)
            if failMessage is not None:
                raise BadRequest(failMessage)
            member.setMemberProperties(properties)
            out.append("User '%s' is added" % row_id)
        else:
Exemplo n.º 29
0
 def test_pm_Speed_get_full_title(self):
     '''Test organization.get_full_title.'''
     self.changeUser('pmManager')
     org = get_organizations()[0]
     # call get_full_title 1000 times
     self._check_get_full_title(org, times=1000)
Exemplo n.º 30
0
 def _get_organizations(self, times=1, caching=True):
     ''' '''
     for time in range(times):
         get_organizations(not_empty_suffix='advisers', caching=caching)