def activate_group_encoder(self, typ='imail'): """ Clean created examples """ if not check_role(self): return "You must be a manager to run this script" portal = api.portal.getSite() # activate group encoder api.portal.set_registry_record('imio.dms.mail.browser.settings.IImioDmsMailConfig.{}_group_encoder'.format(typ), True) # we add organizations orgs = [portal['contacts']['plonegroup-organization']['direction-generale']['secretariat'].UID(), portal['contacts']['plonegroup-organization']['evenements'].UID()] functions = get_registry_functions() for dic in functions: if dic['fct_id'] != CREATING_GROUP_SUFFIX: continue if not dic['fct_orgs']: dic['fct_orgs'] = orgs set_registry_functions(functions) # we add members in groups if 'encodeur' not in [u.getId() for u in api.user.get_users(groupname='{}_{}'.format(orgs[0], CREATING_GROUP_SUFFIX))]: api.group.add_user(groupname='{}_{}'.format(orgs[0], CREATING_GROUP_SUFFIX), username='******') api.group.add_user(groupname='{}_{}'.format(orgs[1], CREATING_GROUP_SUFFIX), username='******') return portal.REQUEST.response.redirect(portal.absolute_url())
def update_site(self): # update front-page frontpage = self.portal['front-page'] if frontpage.Title() == 'Gestion du courrier 2.2': frontpage.setTitle(_("front_page_title")) frontpage.setDescription(_("front_page_descr")) frontpage.setText(_("front_page_text"), mimetype='text/html') # update portal title self.portal.title = 'Gestion du courrier 2.3' # set om folder as default page self.portal.templates.setDefaultPage('om') # change permission to remove dashboard from user menu self.portal.manage_permission('Portlets: Manage own portlets', ('Manager', 'Site Administrator'), acquire=0) # clean old messages if 'doc' in self.portal['messages-config']: api.content.delete(self.portal['messages-config']['doc']) add_message( 'doc', 'Documentation', u'<p>Vous pouvez consulter la <a href="https://docs.imio.be/' u'imio-doc/ia.docs/" target="_blank">documentation en ligne de la ' u'version 2.3</a>, dont <a href="https://docs.imio.be/imio-doc/ia.docs/changelog" ' u'target="_blank">les nouvelles fonctionnalités</a> ainsi que d\'autres documentations liées.</p>', msg_type='significant', can_hide=True, req_roles=['Authenticated'], activate=True) if 'new-version' in self.portal['messages-config']: api.content.delete(self.portal['messages-config']['new-version']) # update plonegroup if not get_registry_groups_mgt(): set_registry_groups_mgt(['dir_general', 'encodeurs', 'expedition']) functions = get_registry_functions() for dic in functions: if dic['fct_id'] == u'encodeur': dic['fct_title'] = u'Créateur CS' set_registry_functions(functions) # add group if api.group.get('lecteurs_globaux_ce') is None: api.group.create('lecteurs_globaux_ce', '2 Lecteurs Globaux CE') # change local roles fti = getUtility(IDexterityFTI, name='dmsincomingmail') # i_e ok lr = getattr(fti, 'localroles') lrsc = lr['static_config'] for state in [ 'proposed_to_manager', 'proposed_to_n_plus_1', 'proposed_to_agent', 'in_treatment', 'closed' ]: if state in lrsc: if 'lecteurs_globaux_ce' not in lrsc[state]: lrsc[state]['lecteurs_globaux_ce'] = {'roles': ['Reader']} lr._p_changed = True # We need to indicate that the object has been modified and must be "saved" # mark tabs to add count on for folder_id in ('incoming-mail', 'outgoing-mail', 'tasks'): folder = self.portal[folder_id] if not ICountableTab.providedBy(folder): alsoProvides(folder, ICountableTab) folder.reindexObject(idxs='object_provides')
def setUp(self): """Custom shared utility setup for tests.""" self.portal = self.layer['portal'] # Organizations creation self.portal.invokeFactory('directory', DEFAULT_DIRECTORY_ID) self.portal[DEFAULT_DIRECTORY_ID].invokeFactory( 'organization', PLONEGROUP_ORG, title='My organization') own_orga = get_own_organization() own_orga.invokeFactory('organization', 'department1', title='Department 1') own_orga.invokeFactory('organization', 'department2', title='Department 2') self.contacts = [own_orga['department1'], own_orga['department2']] set_registry_organizations([c.UID() for c in self.contacts]) set_registry_functions([{ 'fct_title': u'Director', 'fct_id': u'director', 'fct_orgs': [], 'fct_management': False, 'enabled': True }]) self.portal.invokeFactory('acontent', 'acontent1', title='Content 1', pg_organization=self.contacts[0].UID()) self.portal.invokeFactory('acontent', 'acontent2', title='Content 2', pg_organization=self.contacts[1].UID())
def setUp(self): """Custom shared utility setup for tests.""" self.portal = self.layer['portal'] # Organizations creation self.portal.invokeFactory('directory', DEFAULT_DIRECTORY_ID) self.portal[DEFAULT_DIRECTORY_ID].invokeFactory('organization', PLONEGROUP_ORG, title='My organization') own_orga = get_own_organization() own_orga.invokeFactory('organization', 'department1', title='Department 1') own_orga.invokeFactory('organization', 'department2', title='Department 2') own_orga['department1'].invokeFactory('organization', 'service1', title='Service 1') own_orga.invokeFactory('organization', 'inactive_department', title='Inactive department') inactive_department = own_orga['inactive_department'] api.content.transition(obj=inactive_department, transition='deactivate') set_registry_organizations([own_orga['department1'].UID(), own_orga['department1']['service1'].UID(), own_orga['department2'].UID()]) set_registry_functions([{'fct_title': u'Director', 'fct_id': u'director', 'fct_orgs': [], 'fct_management': False, 'enabled': True}, {'fct_title': u'Worker', 'fct_id': u'worker', 'fct_orgs': [], 'fct_management': False, 'enabled': True}])
def test_get_all_suffixes_fct_orgs(self): dep2_uid = self.dep2.UID() self.assertEqual(get_all_suffixes(dep2_uid), [u'observer', u'director']) functions = get_registry_functions() functions[0]['fct_orgs'] = [self.uid] set_registry_functions(functions) self.assertEqual(get_all_suffixes(dep2_uid), [u'director'])
def select_org_for_function(org_uid, function_id, remove=False): """Select an organization UID in the list of fct_orgs of a function.""" functions = get_registry_functions() for function in functions: if function['fct_id'] == function_id: if remove and org_uid in function['fct_orgs']: function['fct_orgs'].remove(org_uid) elif org_uid not in function['fct_orgs']: function['fct_orgs'].append(org_uid) set_registry_functions(functions)
def select_org_for_function(org_uid, function_id, remove=False): """Select an organization UID in the list of fct_orgs of a function.""" functions = get_registry_functions() for function in functions: if function['fct_id'] == function_id: if remove and org_uid in function['fct_orgs']: function['fct_orgs'].remove(org_uid) elif org_uid not in function['fct_orgs']: function['fct_orgs'].append(org_uid) set_registry_functions(functions)
def test_get_all_suffixes_only_enabled(self): dep2_uid = self.dep2.UID() self.assertEqual(get_all_suffixes(dep2_uid, only_enabled=True), [u'observer', u'director']) functions = get_registry_functions() functions[0]['enabled'] = False set_registry_functions(functions) self.assertEqual(get_all_suffixes(dep2_uid, only_enabled=True), [u'director']) self.assertEqual(get_all_suffixes(dep2_uid, only_enabled=False), [u'observer', u'director'])
def test_detectContactPlonegroupChangeDisableFunction(self): """When a function is disabled (enabled=False), every linked Plone groups are deleted as well. This is protected by validateSettings that checks first that every Plone groups are empty.""" own_orga = get_own_organization() dep1 = own_orga['department1'] plone_group_id = get_plone_group_id(dep1.UID(), 'director') self.assertTrue(api.group.get(plone_group_id)) functions = get_registry_functions() # disable 'director' functions[0]['enabled'] = False set_registry_functions(functions) # the linked Plone groups are deleted self.assertFalse(api.group.get(plone_group_id))
def test_detectContactPlonegroupChangeRemoveFunction(self): """When a function is removed, every linked Plone groups are deleted as well. This is protected by validateSettings that checks first that every Plone groups are empty.""" own_orga = get_own_organization() dep1 = own_orga['department1'] plone_group_id = get_plone_group_id(dep1.UID(), 'director') self.assertTrue(api.group.get(plone_group_id)) functions = get_registry_functions() # remove 'director' functions.pop(0) set_registry_functions(functions) # the linked Plone groups are deleted self.assertFalse(api.group.get(plone_group_id))
def test_detectContactPlonegroupChange(self): """Test if group creation works correctly""" group_ids = [group.id for group in api.group.get_groups()] organizations = get_registry_organizations() for uid in organizations: self.assertIn('%s_director' % uid, group_ids) self.assertIn('%s_worker' % uid, group_ids) d1_d_group = api.group.get(groupname='%s_director' % organizations[0]) self.assertEquals(d1_d_group.getProperty('title'), 'Department 1 (Director)') d1s1_d_group = api.group.get(groupname='%s_director' % organizations[1]) self.assertEquals(d1s1_d_group.getProperty('title'), 'Department 1 - Service 1 (Director)') # Changing function title set_registry_functions([{'fct_title': u'Directors', 'fct_id': u'director', 'fct_orgs': [], 'fct_management': False, 'enabled': True}, {'fct_title': u'Worker', 'fct_id': u'worker', 'fct_orgs': [], 'fct_management': False, 'enabled': True}]) d1_d_group = api.group.get(groupname='%s_director' % organizations[0]) self.assertEquals(d1_d_group.getProperty('title'), 'Department 1 (Directors)') d1s1_d_group = api.group.get(groupname='%s_director' % organizations[1]) self.assertEquals(d1s1_d_group.getProperty('title'), 'Department 1 - Service 1 (Directors)') # Adding new organization own_orga = get_own_organization() own_orga['department2'].invokeFactory('organization', 'service2', title='Service 2') # append() method on the registry doesn't trigger the event. += too newValue = get_registry_organizations() + [own_orga['department2']['service2'].UID()] set_registry_organizations(newValue) group_ids = [group.id for group in api.group.get_groups()] last_uid = get_registry_organizations()[-1] self.assertIn('%s_director' % last_uid, group_ids) self.assertIn('%s_worker' % last_uid, group_ids) # Adding new function newValue = get_registry_functions() + [{'fct_title': u'Chief', 'fct_id': u'chief', 'fct_orgs': [], 'fct_management': False, 'enabled': True}] set_registry_functions(newValue) group_ids = [group.id for group in api.group.get_groups() if '_' in group.id] self.assertEquals(len(group_ids), 12) for uid in get_registry_organizations(): self.assertIn('%s_director' % uid, group_ids) self.assertIn('%s_chief' % uid, group_ids) self.assertIn('%s_worker' % uid, group_ids)
def test_onlyRelevantPloneGroupsCreatedWhenFunctionRestrictedToSelectedOrgs(self): """Test using 'fct_orgs' when defining functions.""" # create a new suffix and restrict it to department1 own_orga = get_own_organization() dep1 = own_orga['department1'] dep1_uid = dep1.UID() dep2 = own_orga['department2'] dep2_uid = dep2.UID() functions = get_registry_functions() new_function = {'fct_id': u'new', 'fct_title': u'New', 'fct_orgs': [dep1_uid]} functions.append(new_function) set_registry_functions(functions) # 'new' suffixed Plone group was created only for dep1 self.assertTrue(api.group.get(get_plone_group_id(dep1_uid, u'new'))) self.assertFalse(api.group.get(get_plone_group_id(dep2_uid, u'new')))
def test_detectContactPlonegroupChangeSelectOrgs(self): """When selecting 'fct_orgs' on a function, Plone groups are create/deleted depending on the fact that 'fct_orgs' is empty or contains some organization uids.""" own_orga = get_own_organization() dep1 = own_orga['department1'] dep1_uid = dep1.UID() dep2 = own_orga['department2'] dep2_uid = dep2.UID() dep1_plone_group_id = get_plone_group_id(dep1_uid, 'director') dep2_plone_group_id = get_plone_group_id(dep2_uid, 'director') self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # select dep2_uid for 'director' functions = get_registry_functions() functions[0]['fct_orgs'] = [dep2_uid] set_registry_functions(functions) # dep1 director Plone group is deleted self.assertFalse(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # select dep1_uid for 'director' functions = get_registry_functions() functions[0]['fct_orgs'] = [dep1_uid] set_registry_functions(functions) self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertFalse(api.group.get(dep2_plone_group_id)) # select nothing for 'director', every groups are created functions = get_registry_functions() functions[0]['fct_orgs'] = [] set_registry_functions(functions) self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # select both dep1 and dep2, every groups are created functions = get_registry_functions() functions[0]['fct_orgs'] = [dep1_uid, dep2_uid] set_registry_functions(functions) self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # Changing function title dep1_plone_group = api.group.get(dep1_plone_group_id) self.assertEquals(dep1_plone_group.getProperty('title'), 'Department 1 (Director)') dep2_plone_group = api.group.get(dep2_plone_group_id) self.assertEquals(dep2_plone_group.getProperty('title'), 'Department 2 (Director)') functions[0]['fct_title'] = u'New title' set_registry_functions(functions) dep1_plone_group = api.group.get(dep1_plone_group_id) self.assertEquals(dep1_plone_group.getProperty('title'), 'Department 1 (New title)') dep2_plone_group = api.group.get(dep2_plone_group_id) self.assertEquals(dep2_plone_group.getProperty('title'), 'Department 2 (New title)')
def test_detectContactPlonegroupChangeSelectOrgs(self): """When selecting 'fct_orgs' on a function, Plone groups are create/deleted depending on the fact that 'fct_orgs' is empty or contains some organization uids.""" own_orga = get_own_organization() dep1 = own_orga['department1'] dep1_uid = dep1.UID() dep2 = own_orga['department2'] dep2_uid = dep2.UID() dep1_plone_group_id = get_plone_group_id(dep1_uid, 'director') dep2_plone_group_id = get_plone_group_id(dep2_uid, 'director') self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # select dep2_uid for 'director' functions = get_registry_functions() functions[0]['fct_orgs'] = [dep2_uid] set_registry_functions(functions) # dep1 director Plone group is deleted self.assertFalse(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # select dep1_uid for 'director' functions = get_registry_functions() functions[0]['fct_orgs'] = [dep1_uid] set_registry_functions(functions) self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertFalse(api.group.get(dep2_plone_group_id)) # select nothing for 'director', every groups are created functions = get_registry_functions() functions[0]['fct_orgs'] = [] set_registry_functions(functions) self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # select both dep1 and dep2, every groups are created functions = get_registry_functions() functions[0]['fct_orgs'] = [dep1_uid, dep2_uid] set_registry_functions(functions) self.assertTrue(api.group.get(dep1_plone_group_id)) self.assertTrue(api.group.get(dep2_plone_group_id)) # Changing function title dep1_plone_group = api.group.get(dep1_plone_group_id) self.assertEquals(dep1_plone_group.getProperty('title'), 'Department 1 (Director)') dep2_plone_group = api.group.get(dep2_plone_group_id) self.assertEquals(dep2_plone_group.getProperty('title'), 'Department 2 (Director)') functions[0]['fct_title'] = u'New title' set_registry_functions(functions) dep1_plone_group = api.group.get(dep1_plone_group_id) self.assertEquals(dep1_plone_group.getProperty('title'), 'Department 1 (New title)') dep2_plone_group = api.group.get(dep2_plone_group_id) self.assertEquals(dep2_plone_group.getProperty('title'), 'Department 2 (New title)')
def setUp(self): """Custom shared utility setup for tests.""" self.portal = self.layer['portal'] # Organizations creation self.portal.invokeFactory('directory', DEFAULT_DIRECTORY_ID) self.portal[DEFAULT_DIRECTORY_ID].invokeFactory( 'organization', PLONEGROUP_ORG, title='My organization') self.own_orga = get_own_organization() self.dep1 = api.content.create(container=self.own_orga, type='organization', id='department1', title='Department 1') self.uid = self.dep1.UID() self.dep2 = api.content.create(container=self.own_orga, type='organization', id='department2', title='Department 2') # users and groups api.user.create(u'*****@*****.**', u'dexter', properties={'fullname': u'Dexter Morgan'}) api.user.create(u'*****@*****.**', u'debra', properties={'fullname': u'Debra Morgan'}) self.inv_group = api.group.create(u'investigators', u'Investigators') self.tech_group = api.group.create(u'technicians', u'Technicians') # settings self.registry = getUtility(IRegistry) set_registry_organizations([self.uid]) set_registry_functions([ { 'fct_title': u'Observers', 'fct_id': u'observer', 'fct_orgs': [], 'fct_management': False, 'enabled': True }, { 'fct_title': u'Director', 'fct_id': u'director', 'fct_orgs': [], 'fct_management': False, 'enabled': True }, ])
def test_onlyRelevantPloneGroupsCreatedWhenFunctionRestrictedToSelectedOrgs(self): """Test using 'fct_orgs' when defining functions.""" # create a new suffix and restrict it to department1 own_orga = get_own_organization() dep1 = own_orga['department1'] dep1_uid = dep1.UID() dep2 = own_orga['department2'] dep2_uid = dep2.UID() functions = get_registry_functions() new_function = {'fct_id': u'new', 'fct_title': u'New', 'fct_orgs': [dep1_uid], 'fct_management': False, 'enabled': True} functions.append(new_function) set_registry_functions(functions) # 'new' suffixed Plone group was created only for dep1 self.assertTrue(api.group.get(get_plone_group_id(dep1_uid, u'new'))) self.assertFalse(api.group.get(get_plone_group_id(dep2_uid, u'new')))
def setUp(self): """Custom shared utility setup for tests.""" self.portal = self.layer['portal'] # Organizations creation self.portal.invokeFactory('directory', DEFAULT_DIRECTORY_ID) self.portal[DEFAULT_DIRECTORY_ID].invokeFactory('organization', PLONEGROUP_ORG, title='My organization') own_orga = get_own_organization() own_orga.invokeFactory('organization', 'department1', title='Department 1') own_orga.invokeFactory('organization', 'department2', title='Department 2') self.contacts = [own_orga['department1'], own_orga['department2']] set_registry_organizations([c.UID() for c in self.contacts]) set_registry_functions([{'fct_title': u'Director', 'fct_id': u'director', 'fct_orgs': []}]) self.portal.invokeFactory('acontent', 'acontent1', title='Content 1', pg_organization=self.contacts[0].UID()) self.portal.invokeFactory('acontent', 'acontent2', title='Content 2', pg_organization=self.contacts[1].UID())
def setUp(self): """Custom shared utility setup for tests.""" self.portal = self.layer['portal'] # Organizations creation self.portal.invokeFactory('directory', DEFAULT_DIRECTORY_ID) self.portal[DEFAULT_DIRECTORY_ID].invokeFactory('organization', PLONEGROUP_ORG, title='My organization') own_orga = get_own_organization() own_orga.invokeFactory('organization', 'department1', title='Department 1') own_orga.invokeFactory('organization', 'department2', title='Department 2') own_orga['department1'].invokeFactory('organization', 'service1', title='Service 1') own_orga.invokeFactory('organization', 'inactive_department', title='Inactive department') inactive_department = own_orga['inactive_department'] api.content.transition(obj=inactive_department, transition='deactivate') set_registry_organizations([own_orga['department1'].UID(), own_orga['department1']['service1'].UID(), own_orga['department2'].UID()]) set_registry_functions([{'fct_title': u'Director', 'fct_id': u'director', 'fct_orgs': []}, {'fct_title': u'Worker', 'fct_id': u'worker', 'fct_orgs': []}])
def test_detectContactPlonegroupChange(self): """Test if group creation works correctly""" group_ids = [group.id for group in api.group.get_groups()] organizations = get_registry_organizations() for uid in organizations: self.assertIn('%s_director' % uid, group_ids) self.assertIn('%s_worker' % uid, group_ids) d1_d_group = api.group.get(groupname='%s_director' % organizations[0]) self.assertEquals(d1_d_group.getProperty('title'), 'Department 1 (Director)') d1s1_d_group = api.group.get(groupname='%s_director' % organizations[1]) self.assertEquals(d1s1_d_group.getProperty('title'), 'Department 1 - Service 1 (Director)') # Changing function title set_registry_functions([{'fct_title': u'Directors', 'fct_id': u'director', 'fct_orgs': []}, {'fct_title': u'Worker', 'fct_id': u'worker', 'fct_orgs': []}]) d1_d_group = api.group.get(groupname='%s_director' % organizations[0]) self.assertEquals(d1_d_group.getProperty('title'), 'Department 1 (Directors)') d1s1_d_group = api.group.get(groupname='%s_director' % organizations[1]) self.assertEquals(d1s1_d_group.getProperty('title'), 'Department 1 - Service 1 (Directors)') # Adding new organization own_orga = get_own_organization() own_orga['department2'].invokeFactory('organization', 'service2', title='Service 2') # append() method on the registry doesn't trigger the event. += too newValue = get_registry_organizations() + [own_orga['department2']['service2'].UID()] set_registry_organizations(newValue) group_ids = [group.id for group in api.group.get_groups()] last_uid = get_registry_organizations()[-1] self.assertIn('%s_director' % last_uid, group_ids) self.assertIn('%s_worker' % last_uid, group_ids) # Adding new function newValue = get_registry_functions() + [{'fct_title': u'Chief', 'fct_id': u'chief', 'fct_orgs': []}] set_registry_functions(newValue) group_ids = [group.id for group in api.group.get_groups() if '_' in group.id] self.assertEquals(len(group_ids), 12) for uid in get_registry_organizations(): self.assertIn('%s_director' % uid, group_ids) self.assertIn('%s_chief' % uid, group_ids) self.assertIn('%s_worker' % uid, group_ids)
def setUp(self): """Custom shared utility setup for tests.""" self.portal = self.layer['portal'] # Organizations creation self.portal.invokeFactory('directory', DEFAULT_DIRECTORY_ID) self.portal[DEFAULT_DIRECTORY_ID].invokeFactory( 'organization', PLONEGROUP_ORG, title='My organization') self.own_orga = get_own_organization() self.dep1 = api.content.create(container=self.own_orga, type='organization', id='department1', title='Department 1') self.uid = self.dep1.UID() self.dep2 = api.content.create(container=self.own_orga, type='organization', id='department2', title='Department 2') self.registry = getUtility(IRegistry) set_registry_organizations([self.uid]) set_registry_functions([ { 'fct_title': u'Observers', 'fct_id': u'observer', 'fct_orgs': [], 'fct_management': False, 'enabled': True }, { 'fct_title': u'Director', 'fct_id': u'director', 'fct_orgs': [], 'fct_management': False, 'enabled': True }, ]) api.group.add_user(groupname='%s_director' % self.uid, username=TEST_USER_ID)
def configure_group_encoder(portal_types, contacts_part=False): """ Used to configure a creating function and group for some internal organizations. Update portal_type to add behavior, configure localroles field """ # function functions = get_registry_functions() if CREATING_GROUP_SUFFIX not in [fct['fct_id'] for fct in functions]: functions.append({ 'fct_title': u'Indicateur du service', 'fct_id': CREATING_GROUP_SUFFIX, 'fct_orgs': [], 'fct_management': False, 'enabled': True }) set_registry_functions(functions) if contacts_part and CONTACTS_PART_SUFFIX not in [ fct['fct_id'] for fct in functions ]: functions.append({ 'fct_title': u'Contacts par défaut', 'fct_id': CONTACTS_PART_SUFFIX, 'fct_orgs': [], 'fct_management': False, 'enabled': True }) set_registry_functions(functions) # role and permission portal = api.portal.get() # existing_roles = list(portal.valid_roles()) # if CREATING_FIELD_ROLE not in existing_roles: # existing_roles.append(CREATING_FIELD_ROLE) # portal.__ac_roles__ = tuple(existing_roles) # portal.manage_permission('imio.dms.mail: Write creating group field', # ('Manager', 'Site Administrator', CREATING_FIELD_ROLE), acquire=0) # local roles config config = { 'dmsincomingmail': { # i_e ok 'created': { CREATING_GROUP_SUFFIX: { 'roles': [ 'Contributor', 'Editor', 'DmsFile Contributor', 'Base Field Writer', 'Treating Group Writer' ] } }, # CREATING_FIELD_ROLE]}}, 'proposed_to_manager': { CREATING_GROUP_SUFFIX: { 'roles': ['Base Field Writer', 'Reader'] } }, 'proposed_to_agent': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } }, 'in_treatment': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } }, 'closed': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } } }, 'dmsincoming_email': { 'created': { CREATING_GROUP_SUFFIX: { 'roles': [ 'Contributor', 'Editor', 'DmsFile Contributor', 'Base Field Writer', 'Treating Group Writer' ] } }, # CREATING_FIELD_ROLE]}}, 'proposed_to_manager': { CREATING_GROUP_SUFFIX: { 'roles': ['Base Field Writer', 'Reader'] } }, 'proposed_to_agent': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } }, 'in_treatment': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } }, 'closed': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } } }, 'dmsoutgoingmail': { 'to_be_signed': { CREATING_GROUP_SUFFIX: { 'roles': ['Editor', 'Reviewer'] } }, 'sent': { CREATING_GROUP_SUFFIX: { 'roles': ['Reader', 'Reviewer'] } }, 'scanned': { CREATING_GROUP_SUFFIX: { 'roles': [ 'Contributor', 'Editor', 'Reviewer', 'DmsFile Contributor', 'Base Field Writer', 'Treating Group Writer' ] } }, }, # 'dmsoutgoing_email': { # 'to_be_signed': {CREATING_GROUP_SUFFIX: {'roles': ['Editor', 'Reviewer']}}, # 'sent': {CREATING_GROUP_SUFFIX: {'roles': ['Reader', 'Reviewer']}}, # 'scanned': {CREATING_GROUP_SUFFIX: {'roles': ['Contributor', 'Editor', 'Reviewer', 'DmsFile Contributor', # 'Base Field Writer', 'Treating Group Writer']}}, # }, } # add localroles for possible proposed_to_n_plus_ states # only incoming mails if 'dmsincomingmail' in portal_types: # i_e ok for typ in ('dmsincomingmail', 'dmsincoming_email'): states = list_wf_states(portal, typ) for st_id, st_tit in states: if st_id.startswith('proposed_to_n_plus_'): config[typ][st_id] = { CREATING_GROUP_SUFFIX: { 'roles': ['Reader'] } } # criterias config criterias = { 'dmsincomingmail': ('incoming-mail', 'mail-searches', 'all_mails'), # i_e ok 'dmsoutgoingmail': ('outgoing-mail', 'mail-searches', 'all_mails'), 'organization': ('contacts', 'orgs-searches', 'all_orgs'), 'person': ('contacts', 'persons-searches', 'all_persons'), 'held_position': ('contacts', 'hps-searches', 'all_hps'), 'contact_list': ('contacts', 'cls-searches', 'all_cls'), } for portal_type in portal_types: # behaviors fti = getUtility(IDexterityFTI, name=portal_type) # try: # fti = getUtility(IDexterityFTI, name=portal_type) # except ComponentLookupError: # continue if 'imio.dms.mail.content.behaviors.IDmsMailCreatingGroup' not in fti.behaviors: old_bav = tuple(fti.behaviors) fti.behaviors = tuple( list(fti.behaviors) + ['imio.dms.mail.content.behaviors.IDmsMailCreatingGroup']) ftiModified( fti, ObjectModifiedEvent( fti, DexterityFTIModificationDescription('behaviors', old_bav))) # local roles if config.get(portal_type): msg = add_fti_configuration(portal_type, config[portal_type], keyname='creating_group') if msg: logger.warn(msg) # criterias folder_id, category_id, default_id = criterias.get( portal_type, ('', '', '')) if folder_id: reimport_faceted_config( portal[folder_id][category_id], xml='mail-searches-group-encoder.xml', default_UID=portal[folder_id][category_id][default_id].UID()) # display added field for im and om if not contacts_part: config = {'dmsincomingmail': 'imail', 'dmsoutgoingmail': 'omail'} key = 'imio.dms.mail.browser.settings.IImioDmsMailConfig.{}_fields'.format( config[portal_types[0]]) fields = api.portal.get_registry_record(key) if 'IDmsMailCreatingGroup.creating_group' not in [ f['field_name'] for f in fields ]: fields.append({ 'field_name': 'IDmsMailCreatingGroup.creating_group', 'read_tal_condition': u'', 'write_tal_condition': u'' }) api.portal.set_registry_record(key, fields)
def remove_service_chief(self): # remove collection logger.info('Modifying workflows') for folder in (self.imf['mail-searches'], self.omf['mail-searches']): if 'searchfor_proposed_to_service_chief' in folder: api.content.delete( obj=folder['searchfor_proposed_to_service_chief']) # clean dms config for ptype in ('dmsincomingmail', 'dmsoutgoingmail', 'task'): # i_e ok config = get_dms_config(['review_levels', ptype]) if '_validateur' in config: del config['_validateur'] set_dms_config(keys=['review_levels', ptype], value=config) config = get_dms_config(['review_states', ptype]) if 'proposed_to_service_chief' in config: del config['proposed_to_service_chief'] set_dms_config(keys=['review_states', ptype], value=config) def remove_localrole_validateur(dic1): for state1 in dic1: if 'validateur' in dic1[state1]: del dic1[state1]['validateur'] # clean local roles for ptype in ('dmsincomingmail', 'dmsoutgoingmail'): # i_e ok fti = getUtility(IDexterityFTI, name=ptype) lr = getattr(fti, 'localroles') lrg = lr['static_config'] if 'proposed_to_service_chief' in lrg: del lrg['proposed_to_service_chief'] remove_localrole_validateur(lrg) lrg = lr['treating_groups'] if 'proposed_to_service_chief' in lrg: del lrg['proposed_to_service_chief'] remove_localrole_validateur(lrg) lrg = lr['recipient_groups'] if 'proposed_to_service_chief' in lrg: del lrg['proposed_to_service_chief'] remove_localrole_validateur(lrg) lr._p_changed = True # on task fti = getUtility(IDexterityFTI, name='task') lr = getattr(fti, 'localroles') lrg = lr['assigned_group'] if 'validateur' in lrg['to_do']: remove_localrole_validateur(lrg) lrg = lr['parents_assigned_groups'] if 'validateur' in lrg['to_do']: remove_localrole_validateur(lrg) lr._p_changed = True # update registry lst = api.portal.get_registry_record( 'imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions' ) for entry in ('dmsincomingmail.back_to_service_chief|', 'dmsoutgoingmail.back_to_service_chief|'): if entry not in lst: break lst.remove(entry) else: api.portal.set_registry_record( 'imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions', lst) # update remark states for attr in ('imail_remark_states', 'omail_remark_states'): lst = (api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.{}'.format( attr)) or []) if 'proposed_to_service_chief' in lst: lst.remove('proposed_to_service_chief') api.portal.set_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.{}'. format(attr), lst) # Manage workflows and wfadaptations functions = get_registry_functions() if 'validateur' not in [fct['fct_id'] for fct in functions]: return # apply the following only once def remove_adaptation_from_registry(name): record = api.portal.get_registry_record(RECORD_NAME) api.portal.set_registry_record( RECORD_NAME, [d for d in record if d['adaptation'] != name]) # reset workflows self.runProfileSteps('imio.dms.mail', steps=['workflow']) # self.portal.portal_workflow.updateRoleMappings() # done later # Apply workflow adaptations if necessary applied_wfa = [dic['adaptation'] for dic in get_applied_adaptations()] n_plus_1_params = { 'validation_level': 1, 'state_title': u'À valider par le chef de service', 'forward_transition_title': u'Proposer au chef de service', 'backward_transition_title': u'Renvoyer au chef de service', 'function_title': u'N+1' } task_adapt = True for wkf, acr in (('incomingmail_workflow', 'IM'), ('outgoingmail_workflow', 'OM')): if u'imio.dms.mail.wfadaptations.{}SkipProposeToServiceChief'.format( acr) in applied_wfa: remove_adaptation_from_registry( u'imio.dms.mail.wfadaptations.{}SkipProposeToServiceChief'. format(acr)) task_adapt = False if acr == 'OM': folder = self.omf['mail-searches'] if folder['to_validate'].enabled: folder['to_validate'].enabled = False folder['to_validate'].reindexObject() else: logger.info( 'Applying {}ServiceValidation wf adaptation'.format(acr)) sva = getattr(wfadaptations, '{}ServiceValidation'.format(acr))() sva.reapply = True adapt_is_applied = sva.patch_workflow(wkf, **n_plus_1_params) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.{}ServiceValidation'. format(acr), wkf, True, **n_plus_1_params) # update task_workflow update_task_workflow(self.portal) if task_adapt: tsva = TaskServiceValidation() adapt_is_applied = tsva.patch_workflow('task_workflow', **{}) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.TaskServiceValidation', 'task_workflow', False) else: # update collections folder = self.portal['tasks']['task-searches'] for cid in ('to_assign', 'to_close'): if folder[cid].enabled: folder[cid].enabled = False folder[cid].reindexObject() invalidate_cachekey_volatile_for( 'collective.eeafaceted.collectionwidget.cachedcollectionvocabulary' ) # replace EmergencyZoneAdaptation im_workflow = self.wtool['incomingmail_workflow'] if u'imio.dms.mail.wfadaptations.EmergencyZone' in applied_wfa: state = im_workflow.states['proposed_to_manager'] state.title = u'À valider par le CZ'.encode('utf8') for tr, tit in (('back_to_manager', u'Renvoyer au CZ'), ('propose_to_manager', u'Proposer au CZ')): transition = im_workflow.transitions[tr] transition.title = tit.encode('utf8') logger.info('Removing EmergencyZone wf adaptation') remove_adaptation_from_registry( u'imio.dms.mail.wfadaptations.EmergencyZone') # redo OMToPrintAdaptation if u'imio.dms.mail.wfadaptations.OMToPrint' in applied_wfa: logger.info('Applying OMToPrint wf adaptation') tpa = OMToPrintAdaptation() tpa.patch_workflow('outgoingmail_workflow') # redo IMPreManagerValidation if u'imio.dms.mail.wfadaptations.IMPreManagerValidation' in applied_wfa: logger.info('Applying IMPreManagerValidation wf adaptation') params = [ dic['parameters'] for dic in get_applied_adaptations() if dic['adaptation'] == u'imio.dms.mail.wfadaptations.IMPreManagerValidation' ][0] remove_adaptation_from_registry( u'imio.dms.mail.wfadaptations.IMPreManagerValidation') del params['collection_title'] pmva = IMPreManagerValidation() adapt_is_applied = pmva.patch_workflow('incomingmail_workflow', **params) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.IMPreManagerValidation', 'incoming_mail', False, **params) # update wf history to replace review_state and correct history config = { 'dmsincomingmail': { 'wf': 'incomingmail_workflow', # i_e ok 'st': { 'proposed_to_service_chief': 'proposed_to_n_plus_1' }, 'tr': { 'propose_to_service_chief': 'propose_to_n_plus_1', 'back_to_service_chief': 'back_to_n_plus_1' } }, 'dmsoutgoingmail': { 'wf': 'outgoingmail_workflow', 'st': { 'proposed_to_service_chief': 'proposed_to_n_plus_1' }, 'tr': { 'propose_to_service_chief': 'propose_to_n_plus_1', 'back_to_service_chief': 'back_to_n_plus_1' } } } for pt in config: logger.info('Updating history and indexes of {} type'.format(pt)) for i, brain in enumerate(self.catalog(portal_type=pt), 1): obj = brain.getObject() if i % 10000 == 0: logger.info('On brain {}'.format(i)) # update history wfh = [] wkf = self.wtool[config[pt]['wf']] for status in obj.workflow_history.get(config[pt]['wf']): # replace old state by new one if status['review_state'] in config[pt]['st']: status['review_state'] = config[pt]['st'][ status['review_state']] # replace old transition by new one if status['action'] in config[pt]['tr']: status['action'] = config[pt]['tr'][status['action']] wfh.append(status) obj.workflow_history[config[pt]['wf']] = tuple(wfh) # update permissions and roles wkf.updateRoleMappingsFor(obj) # update state_group (use dms_config), permissions, state obj.reindexObject(idxs=[ 'allowedRolesAndUsers', 'review_state', 'state_group' ]) for child in obj.objectValues(): child.reindexObject(idxs=['allowedRolesAndUsers']) # migrate plone groups # First unregister group deletion handlers globalSiteManager.unregisterHandler(pg_group_deleted, (IGroupDeletedEvent, )) globalSiteManager.unregisterHandler(group_deleted, (IGroupDeletedEvent, )) globalSiteManager.unregisterHandler(group_assignment, (IPrincipalAddedToGroupEvent, )) globalSiteManager.unregisterHandler( group_unassignment, (IPrincipalRemovedFromGroupEvent, )) # move users from _validateur to _n_plus_1 for group in api.group.get_groups(): if group.id.endswith('_validateur'): org = group.id.split('_')[0] np1group = api.group.get('{}_n_plus_1'.format(org)) if np1group: for user in api.user.get_users(group=group): api.group.add_user(group=np1group, user=user) api.group.remove_user(group=group, user=user) api.group.delete(group=group) # register again group deletion handlers globalSiteManager.registerHandler(pg_group_deleted, (IGroupDeletedEvent, )) globalSiteManager.registerHandler(group_deleted, (IGroupDeletedEvent, )) globalSiteManager.registerHandler(group_assignment, (IPrincipalAddedToGroupEvent, )) globalSiteManager.registerHandler(group_unassignment, (IPrincipalRemovedFromGroupEvent, )) # remove validateur function functions = get_registry_functions() if 'validateur' in [fct['fct_id'] for fct in functions]: set_registry_functions( [fct for fct in functions if fct['fct_id'] != 'validateur'])
def remove_useless_functions(self): """ Remove groups that are not used in our custom workflow """ def filter_list(list, filter_out): kept = [] for item in list: if item not in filter_out: kept.append(item) return kept for cfg in self.tool.objectValues("MeetingConfig"): adviceAnnexConfidentialVisibleFor = filter_list( list(cfg.getAdviceAnnexConfidentialVisibleFor()), [ "suffix_proposing_group_prereviewers", "suffix_proposing_group_budgetimpactreviewers", "suffix_proposing_group_reviewers", ], ) cfg.setAdviceAnnexConfidentialVisibleFor( adviceAnnexConfidentialVisibleFor) itemAnnexConfidentialVisibleFor = filter_list( list(cfg.getItemAnnexConfidentialVisibleFor()), [ "suffix_proposing_group_prereviewers", "suffix_proposing_group_budgetimpactreviewers", "suffix_proposing_group_reviewers", ], ) cfg.setItemAnnexConfidentialVisibleFor( itemAnnexConfidentialVisibleFor) meetingAnnexConfidentialVisibleFor = filter_list( list(cfg.getMeetingAnnexConfidentialVisibleFor()), [ "suffix_profile_prereviewers", "suffix_profile_budgetimpactreviewers", "suffix_profile_reviewers", ], ) cfg.setMeetingAnnexConfidentialVisibleFor( meetingAnnexConfidentialVisibleFor) cfg.processForm() cfg.reindexObject() groups = api.group.get_groups() for group in groups: grp_id = group.id if grp_id.endswith("_reviewers") or grp_id.endswith( "_prereviewers"): for member in group.getAllGroupMemberIds(): group.removeMember(member) functions = get_registry_functions() functions_result = [] for function in functions: if function["fct_id"] not in (u"prereviewers", u"reviewers"): functions_result.append(function) set_registry_functions(functions_result)
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
def test_pm_PloneGroupSettingsFunctionsValidator(self): """Completed plonegroup settings validation with our use cases : - can not remove a suffix if used in MeetingConfig.selectableCopyGroups; - can not remove a suffix if used in MeetingItem.copyGroups; - can not remove a suffix if used as composed value, so like 'suffix_proposing_group_level1reviewers', in MeetingConfig.itemAnnexConfidentialVisibleFor for example; - can not remove a suffix used by MeetingConfig.itemWFValidationLevels.""" # make sure we use default itemWFValidationLevels, # useful when test executed with custom profile cfg = self.meetingConfig self._setUpDefaultItemWFValidationLevels(cfg) def _check(validation_error_msg, checks=['without', 'disabled', 'fct_orgs']): """ """ values = [] if 'without' in checks: values.append(functions_without_samplers) if 'disabled' in checks: values.append(functions_with_disabled_samplers) if 'fct_orgs' in checks: values.append(functions_with_fct_orgs_samplers) for value in values: with self.assertRaises(Invalid) as cm: validator.validate(value) self.assertEqual(cm.exception.message, validation_error_msg) self.changeUser('siteadmin') # add a new suffix and play with it functions = get_registry_functions() functions_without_samplers = deepcopy(functions) functions.append({ 'enabled': True, 'fct_management': False, 'fct_id': u'samplers', 'fct_orgs': [], 'fct_title': u'Samplers' }) functions_with_disabled_samplers = deepcopy(functions) functions_with_disabled_samplers[-1]['enabled'] = False functions_with_fct_orgs_samplers = deepcopy(functions) functions_with_fct_orgs_samplers[-1]['fct_orgs'] = [self.vendors_uid] validator = PloneGroupSettingsFunctionsValidator( self.portal, self.request, None, IContactPlonegroupConfig['functions'], None) self.assertIsNone(validator.validate(functions)) set_registry_functions(functions) # use samplers suffix self._enableItemValidationLevel(cfg, level='prevalidated', suffix='samplers') # developers_samplers was created dev_samplers = get_plone_group(self.developers_uid, 'samplers') dev_samplers_id = dev_samplers.getId() self.assertTrue(dev_samplers in api.group.get_groups()) # use samplers in MeetingConfig cfg.setSelectableCopyGroups(cfg.getSelectableCopyGroups() + (dev_samplers_id, )) validation_error_msg = _('can_not_delete_plone_group_meetingconfig', mapping={'cfg_url': cfg.absolute_url()}) _check(validation_error_msg) # also check composed values like 'suffix_proposing_group_level1reviewers' cfg.setSelectableCopyGroups(()) cfg.setItemAnnexConfidentialVisibleFor( ('suffix_proposing_group_samplers', )) _check(validation_error_msg, checks=['without', 'disabled']) cfg.setItemAnnexConfidentialVisibleFor(()) # use samplers on item, remove it from MeetingConfig self.changeUser('pmCreator1') item = self.create('MeetingItem') item.setCopyGroups((dev_samplers_id, )) item.reindexObject() # still complaining about config because used in itemWFValidationLevels _check(validation_error_msg, checks=['without', 'disabled']) self._disableItemValidationLevel(cfg, level='prevalidated', suffix='prereviewers') validation_error_msg = _('can_not_delete_plone_group_meetingitem', mapping={'item_url': item.absolute_url()}) _check(validation_error_msg) # remove it on item, then everything is correct item.setCopyGroups(()) item.reindexObject() self.assertIsNone(validator.validate(functions)) set_registry_functions(functions_without_samplers) self.assertFalse(dev_samplers in api.group.get_groups()) # an _advisers may not be disabled if used item.setOptionalAdvisers((self.developers_uid, )) item._update_after_edit(idxs=['indexAdvisers']) functions_with_fct_orgs_advisers = deepcopy(functions) self.assertEqual(functions_with_fct_orgs_advisers[0]['fct_id'], u'advisers') functions_with_fct_orgs_advisers[0]['fct_orgs'] = [self.vendors_uid] with self.assertRaises(Invalid) as cm: validator.validate(functions_with_fct_orgs_advisers) self.assertEqual(cm.exception.message, validation_error_msg) # but if disabling another level it is correct # disable level prereviewers for vendors functions_with_fct_orgs_prereviewers = deepcopy(functions) self.assertEqual(functions_with_fct_orgs_advisers[3]['fct_id'], u'prereviewers') functions_with_fct_orgs_prereviewers[3]['fct_orgs'] = [ self.vendors_uid ] self.assertIsNone( validator.validate(functions_with_fct_orgs_prereviewers)) # remove adviser so it validates item.setOptionalAdvisers(()) item._update_after_edit(idxs=['indexAdvisers']) self.assertIsNone(validator.validate(functions_with_fct_orgs_advisers)) set_registry_functions(functions_with_fct_orgs_advisers) self.assertFalse(self.developers_advisers in api.group.get_groups())