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 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 test_validateSettingsRemoveFunction(self): """A function may only be removed if every linked Plone groups are empty.""" # add a user to group department1 director own_orga = get_own_organization() dep1 = own_orga['department1'] plone_group_id = get_plone_group_id(dep1.UID(), 'director') api.group.add_user(groupname=plone_group_id, username=TEST_USER_ID) invariants = validator.InvariantsValidator( None, None, None, settings.IContactPlonegroupConfig, None) orgs = get_registry_organizations() functions = get_registry_functions() data = {'organizations': orgs, 'functions': functions} # for now it validates correctly self.assertFalse(invariants.validate(data)) # remove 'director' functions.pop(0) errors = invariants.validate(data) self.assertTrue(isinstance(errors[0], Invalid)) error_msg = translate( msgid=u"can_not_remove_function_every_plone_groups_not_empty", domain='collective.contact.plonegroup', mapping={'removed_function': 'director', 'plone_group_id': plone_group_id}) self.assertEqual(translate(errors[0].message), error_msg) # remove user from plone group, now it validates api.group.remove_user(groupname=plone_group_id, username=TEST_USER_ID) self.assertFalse(invariants.validate(data))
def test_validateSettingsSelectFunctionOrgsOnExistingFunction(self): """Selecting 'fct_orgs' for an existing function (so for which Plone groups are already created), is only possible if groups that will be deleted (Plone groups of organizations not selected as 'fct_orgs') are empty.""" # add a user to group department1 director own_orga = get_own_organization() dep1 = own_orga['department1'] dep2 = own_orga['department2'] plone_group_id = get_plone_group_id(dep1.UID(), 'director') api.group.add_user(groupname=plone_group_id, username=TEST_USER_ID) invariants = validator.InvariantsValidator( None, None, None, settings.IContactPlonegroupConfig, None) orgs = get_registry_organizations() functions = get_registry_functions() data = {'organizations': orgs, 'functions': functions} # set dep2 as 'fct_orgs' of 'director' function director = functions[0] director['fct_orgs'] = [dep2.UID()] errors = invariants.validate(data) self.assertTrue(isinstance(errors[0], Invalid)) error_msg = translate( msgid=u"can_not_select_function_orgs_every_other_plone_groups_not_empty", domain='collective.contact.plonegroup', mapping={'function': 'director', 'plone_group_id': plone_group_id}) self.assertEqual(translate(errors[0].message), error_msg) # remove user from plone group, now it validates api.group.remove_user(groupname=plone_group_id, username=TEST_USER_ID) self.assertFalse(invariants.validate(data))
def AssignedUsersWithDeactivatedVocabulary__call__(self, context): factory = getUtility(IVocabularyFactory, 'plone.principalsource.Users') vocab = factory(context) # terms as username, userid, fullname a_terms = [] d_terms = [] active_orgs = get_registry_organizations() functions = [dic['fct_id'] for dic in get_registry_functions()] for term in vocab: for group in api.group.get_groups(username=term.value): if group.id == 'AuthenticatedUsers': continue parts = group.id.split('_') if len(parts) != 1: group_suffix = '_'.join(parts[1:]) if group_suffix in functions and parts[ 0] not in active_orgs: # not an active org continue term.title = term.title.decode('utf8') a_terms.append(term) break else: term.title = _tr( '${element_title} (Inactive)', mapping={'element_title': safe_unicode(term.title)}) d_terms.append(term) return SimpleVocabulary( [SimpleTerm(EMPTY_STRING, EMPTY_STRING, _('Empty value'))] + humansorted(a_terms, key=attrgetter('title')) + humansorted(d_terms, key=attrgetter('title')))
def test_TaskServiceValidation1(self): """ Test TaskServiceValidation adaptations """ # is function added self.assertIn('n_plus_1', [fct['fct_id'] for fct in get_registry_functions()]) # is local roles modified fti = getUtility(IDexterityFTI, name='task') lr = getattr(fti, 'localroles') self.assertIn('n_plus_1', lr['assigned_group']['to_do']) self.assertIn('n_plus_1', lr['parents_assigned_groups']['to_do']) for ptype in ('ClassificationFolder', 'ClassificationSubfolder'): fti = getUtility(IDexterityFTI, name=ptype) lr = getattr(fti, 'localroles') self.assertIn('n_plus_1', lr['treating_groups']['active'], ptype) self.assertIn('n_plus_1', lr['recipient_groups']['active'], ptype) # check collection folder = self.portal['tasks']['task-searches'] self.assertTrue(folder['to_assign'].enabled) self.assertTrue(folder['to_close'].enabled) self.assertFalse(folder['to_treat_in_my_group'].showNumberOfItems) # check annotations config = get_dms_config(['review_levels', 'task']) self.assertIn('_n_plus_1', config) config = get_dms_config(['review_states', 'task']) self.assertIn('to_assign', config) self.assertIn('realized', config)
def test_validateSettingsSelectFunctionOrgsOnExistingFunction(self): """Selecting 'fct_orgs' for an existing function (so for which Plone groups are already created), is only possible if groups that will be deleted (Plone groups of organizations not selected as 'fct_orgs') are empty.""" # add a user to group department1 director own_orga = get_own_organization() dep1 = own_orga['department1'] dep2 = own_orga['department2'] plone_group_id = get_plone_group_id(dep1.UID(), 'director') api.group.add_user(groupname=plone_group_id, username=TEST_USER_ID) invariants = validator.InvariantsValidator( None, None, None, settings.IContactPlonegroupConfig, None) orgs = get_registry_organizations() functions = get_registry_functions() data = {'organizations': orgs, 'functions': functions} # set dep2 as 'fct_orgs' of 'director' function director = functions[0] director['fct_orgs'] = [dep2.UID()] errors = invariants.validate(data) self.assertTrue(isinstance(errors[0], Invalid)) error_msg = translate( msgid=u"can_not_select_function_orgs_every_other_plone_groups_not_empty", domain='collective.contact.plonegroup', mapping={'function': 'director', 'plone_group_id': plone_group_id}) self.assertEqual(translate(errors[0].message), error_msg) # remove user from plone group, now it validates api.group.remove_user(groupname=plone_group_id, username=TEST_USER_ID) self.assertFalse(invariants.validate(data))
def test_validateSettingsDisableFunction(self): """A function may only be disabled (enabled=False) if every linked Plone groups are empty.""" # add a user to group department1 director own_orga = get_own_organization() dep1 = own_orga['department1'] plone_group_id = get_plone_group_id(dep1.UID(), 'director') api.group.add_user(groupname=plone_group_id, username=TEST_USER_ID) invariants = validator.InvariantsValidator( None, None, None, settings.IContactPlonegroupConfig, None) orgs = get_registry_organizations() functions = get_registry_functions() data = {'organizations': orgs, 'functions': functions} # for now it validates correctly self.assertFalse(invariants.validate(data)) # disable 'director' functions[0]['enabled'] = False errors = invariants.validate(data) self.assertTrue(isinstance(errors[0], Invalid)) error_msg = translate( msgid=u"can_not_disable_suffix_plone_groups_not_empty", domain='collective.contact.plonegroup', mapping={'removed_function': 'director', 'plone_group_id': plone_group_id}) self.assertEqual(translate(errors[0].message), error_msg) # remove user from plone group, now it validates api.group.remove_user(groupname=plone_group_id, username=TEST_USER_ID) self.assertFalse(invariants.validate(data))
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 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 __call__(self, context): functions = get_registry_functions() terms = [] for function in functions: terms.append( SimpleTerm(function['fct_id'], function['fct_id'], function['fct_title'])) return SimpleVocabulary(terms)
def addOrModifyOrganizationGroups(organization, uid): """ Modify groups linked to an organization """ changes = False for dic in get_registry_functions(): if addOrModifyGroup(organization, dic['fct_id'], dic['fct_title']): changes = True return changes
def test_select_org_for_function(self): """ """ self.assertEqual(get_registry_functions(), [{ 'fct_title': u'Observers', 'fct_orgs': [], 'fct_id': u'observer', 'fct_management': False, 'enabled': True }, { 'fct_title': u'Director', 'fct_orgs': [], 'fct_id': u'director', 'fct_management': False, 'enabled': True }]) select_org_for_function(self.uid, 'director') self.assertTrue(self.uid in get_registry_functions()[1]['fct_orgs']) select_org_for_function(self.uid, 'director', remove=True) self.assertFalse(self.uid in get_registry_functions()[1]['fct_orgs'])
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 get_all_suffixes(org_uid=None, only_enabled=True): """ Get every suffixes defined in the configuration. """ functions = get_registry_functions() return [ function['fct_id'] for function in functions if (not only_enabled or function['enabled']) and ( not org_uid or not function['fct_orgs'] or org_uid in function['fct_orgs']) ]
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_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 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 test_IMServiceValidation1(self): """ Test IMServiceValidation adaptations """ # is function added self.assertIn('n_plus_1', [fct['fct_id'] for fct in get_registry_functions()]) # is local roles modified for ptype in ('dmsincomingmail', 'dmsincoming_email'): fti = getUtility(IDexterityFTI, name=ptype) lr = getattr(fti, 'localroles') self.assertIn('proposed_to_n_plus_1', lr['static_config'], ptype) self.assertIn('proposed_to_n_plus_1', lr['treating_groups'], ptype) self.assertIn('proposed_to_n_plus_1', lr['recipient_groups'], ptype) for ptype in ('ClassificationFolder', 'ClassificationSubfolder'): fti = getUtility(IDexterityFTI, name=ptype) lr = getattr(fti, 'localroles') self.assertIn('n_plus_1', lr['treating_groups']['active'], ptype) self.assertIn('n_plus_1', lr['recipient_groups']['active'], ptype) # check collection folder = self.portal['incoming-mail']['mail-searches'] self.assertIn('searchfor_proposed_to_n_plus_1', folder) self.assertEqual( folder.getObjectPosition('searchfor_proposed_to_agent'), 13) self.assertEqual( folder.getObjectPosition('searchfor_proposed_to_n_plus_1'), 12) self.assertFalse(folder['to_treat_in_my_group'].showNumberOfItems) # check annotations config = get_dms_config(['review_levels', 'dmsincomingmail']) self.assertIn('_n_plus_1', config) config = get_dms_config(['review_states', 'dmsincomingmail']) self.assertIn('proposed_to_n_plus_1', config) config = get_dms_config(['transitions_auc', 'dmsincomingmail']) self.assertIn('propose_to_n_plus_1', config) config = get_dms_config(['transitions_levels', 'dmsincomingmail']) self.assertEqual(config['proposed_to_manager'].values()[0][0], 'propose_to_n_plus_1') self.assertEqual(config['proposed_to_agent'].values()[0][1], 'back_to_n_plus_1') wf_from_to = get_dms_config( ['wf_from_to', 'dmsincomingmail', 'n_plus']) self.assertListEqual(wf_from_to['to'], [('closed', 'close'), ('proposed_to_agent', 'propose_to_agent'), ('proposed_to_n_plus_1', 'propose_to_n_plus_1')]) # check vocabularies factory = getUtility( IVocabularyFactory, u'collective.eeafaceted.collectionwidget.cachedcollectionvocabulary' ) self.assertEqual(len(factory(folder, folder)), 16) factory = getUtility(IVocabularyFactory, u'imio.dms.mail.IMReviewStatesVocabulary') self.assertEqual(len(factory(folder)), 6) # check configuration lst = api.portal.get_registry_record( 'imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions' ) self.assertIn('dmsincomingmail.back_to_n_plus_1|', lst) self.assertIn('dmsincoming_email.back_to_n_plus_1|', lst) lst = api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.imail_remark_states' ) self.assertIn('proposed_to_n_plus_1', lst)
def test_OMServiceValidation1(self): """ Test OMServiceValidation adaptations """ # is function added self.assertIn('n_plus_1', [fct['fct_id'] for fct in get_registry_functions()]) # is local roles modified fti = getUtility(IDexterityFTI, name='dmsoutgoingmail') lr = getattr(fti, 'localroles') self.assertIn('proposed_to_n_plus_1', lr['treating_groups']) self.assertIn('proposed_to_n_plus_1', lr['recipient_groups']) self.assertIn('validated', lr['treating_groups']) self.assertIn('validated', lr['recipient_groups']) for ptype in ('ClassificationFolder', 'ClassificationSubfolder'): fti = getUtility(IDexterityFTI, name=ptype) lr = getattr(fti, 'localroles') self.assertIn('n_plus_1', lr['treating_groups']['active'], ptype) self.assertIn('n_plus_1', lr['recipient_groups']['active'], ptype) # check collection folder = self.portal['outgoing-mail']['mail-searches'] self.assertIn('searchfor_proposed_to_n_plus_1', folder) self.assertIn('searchfor_validated', folder) self.assertEqual( folder.getObjectPosition('searchfor_proposed_to_n_plus_1'), 10) self.assertEqual(folder.getObjectPosition('searchfor_validated'), 11) self.assertEqual(folder.getObjectPosition('searchfor_to_be_signed'), 12) self.assertIn('proposed_to_n_plus_1', [ dic['v'] for dic in folder['om_treating'].query if dic['i'] == 'review_state' ][0]) self.assertIn('validated', [ dic['v'] for dic in folder['om_treating'].query if dic['i'] == 'review_state' ][0]) self.assertTrue(folder['to_validate'].enabled) # check annotations config = get_dms_config(['review_levels', 'dmsoutgoingmail']) self.assertIn('_n_plus_1', config) config = get_dms_config(['review_states', 'dmsoutgoingmail']) self.assertIn('proposed_to_n_plus_1', config) # check vocabularies factory = getUtility( IVocabularyFactory, u'collective.eeafaceted.collectionwidget.cachedcollectionvocabulary' ) self.assertEqual(len(factory(folder, folder)), 14) factory = getUtility(IVocabularyFactory, u'imio.dms.mail.OMReviewStatesVocabulary') self.assertEqual(len(factory(folder)), 6) # check configuration lst = api.portal.get_registry_record( 'imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions' ) self.assertIn('dmsoutgoingmail.back_to_n_plus_1|', lst) self.assertIn('dmsoutgoingmail.back_to_validated|', lst) lst = api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.omail_remark_states' ) self.assertIn('proposed_to_n_plus_1', lst) self.assertIn('validated', lst)
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 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)
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 get_manageable_functions(self): """ get all manageable functions """ for fct in get_registry_functions(as_copy=False): if fct['fct_management']: self.functions[fct['fct_id']] = fct['fct_title'] return self.functions.keys()
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 test_configure_group_encoder(self): setRoles(self.portal, TEST_USER_ID, ['Manager']) # activate imail group encoder activate_group_encoder(self.portal) self.assertIn(CREATING_GROUP_SUFFIX, [fct['fct_id'] for fct in get_registry_functions()]) for portal_type in ('dmsincomingmail', 'dmsincoming_email'): fti = getUtility(IDexterityFTI, name=portal_type) self.assertIn( 'imio.dms.mail.content.behaviors.IDmsMailCreatingGroup', fti.behaviors) self.assertIn('creating_group', [tup[0] for tup in get_localrole_fields(fti)]) self.assertTrue( fti.localroles.get('creating_group')) # config dic not empty crit = ICriteria(self.portal['incoming-mail']['mail-searches']) self.assertIn('c90', crit.keys()) fields = api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.imail_fields') self.assertIn('IDmsMailCreatingGroup.creating_group', [f['field_name'] for f in fields]) # activate omail group encoder activate_group_encoder(self.portal, typ='omail') self.assertIn(CREATING_GROUP_SUFFIX, [fct['fct_id'] for fct in get_registry_functions()]) # for portal_type in ('dmsoutgoingmail', 'dmsoutgoing_email'): for portal_type in ('dmsoutgoingmail', ): fti = getUtility(IDexterityFTI, name=portal_type) self.assertIn( 'imio.dms.mail.content.behaviors.IDmsMailCreatingGroup', fti.behaviors, portal_type) self.assertIn('creating_group', [tup[0] for tup in get_localrole_fields(fti)], portal_type) self.assertTrue(fti.localroles.get('creating_group'), portal_type) # config dic not empty crit = ICriteria(self.portal['outgoing-mail']['mail-searches']) self.assertIn('c90', crit.keys()) fields = api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.omail_fields') self.assertIn('IDmsMailCreatingGroup.creating_group', [f['field_name'] for f in fields]) # activate contact group encoder activate_group_encoder(self.portal, typ='contact') self.assertIn(CREATING_GROUP_SUFFIX, [fct['fct_id'] for fct in get_registry_functions()]) self.assertIn(CONTACTS_PART_SUFFIX, [fct['fct_id'] for fct in get_registry_functions()]) for portal_type in ('organization', 'person', 'held_position', 'contact_list'): fti = getUtility(IDexterityFTI, name=portal_type) self.assertIn( 'imio.dms.mail.content.behaviors.IDmsMailCreatingGroup', fti.behaviors) self.assertIn('creating_group', [tup[0] for tup in get_localrole_fields(fti)]) for fid in ('orgs-searches', 'persons-searches', 'hps-searches', 'cls-searches'): crit = ICriteria(self.portal['contacts'][fid]) self.assertIn('c90', crit.keys())
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_management_view(self): view = self.portal.unrestrictedTraverse('@@manage-own-groups-users') # No groups activated self.assertListEqual(view.get_manageable_groups(), []) self.assertListEqual(view.get_manageable_functions(), []) # we activate groups and functions functions = get_registry_functions(as_copy=False) functions[0]['fct_management'] = True set_registry_groups_mgt(['investigators']) view.init() self.assertListEqual(view.get_manageable_groups(), ['investigators']) self.assertListEqual(view.get_manageable_functions(), [u'observer']) view.get_user_manageable_groups() # fill in view.groupids view.get_user_manageable_functions() # fill in view.functions_orgs self.assertDictEqual(view.groupids, {}) self.assertDictEqual(view.functions_orgs, {}) # we add the current user to the activated groups, so he can manage it api.group.add_user(groupname='investigators', username=TEST_USER_ID) api.group.add_user(groupname='{}_observer'.format(self.uid), username=TEST_USER_ID) def get_user_groups(userid): return [ g.id for g in api.group.get_groups(username=userid) if g.id not in ['AuthenticatedUsers'] ] self.assertListEqual( get_user_groups(TEST_USER_ID), ['{}_observer'.format(self.uid), u'investigators']) view = self.portal.unrestrictedTraverse('@@manage-own-groups-users') view.init() self.assertListEqual(view.get_manageable_groups(), ['investigators']) self.assertListEqual(view.get_manageable_functions(), [u'observer']) view.get_user_manageable_groups() # fill in view.groupids view.get_user_manageable_functions() # fill in view.functions_orgs self.assertDictEqual(view.groupids, {u'investigators': u'Investigators'}) self.assertDictEqual(view.functions_orgs, {'observer': [self.dep1]}) # we check the values given to the fields view.update() self.assertListEqual(view.fieldnames, ['_groups_', 'observer', '_old_values_']) content = view.getContent() self.assertListEqual(content._groups_, [{ 'group': u'investigators', 'user': '******' }]) self.assertListEqual(content.observer, [{ 'group': self.uid, 'user': '******' }]) old_values = ( "{{'_groups_': [{{'group': u'investigators', 'user': '******'}}], 'observer': " "[{{'group': '{}', 'user': '******'}}]}}".format(self.uid)) self.assertEqual(content._old_values_, old_values) # applying form : we add users self.assertListEqual(get_user_groups('dexter'), []) self.assertListEqual(get_user_groups('debra'), []) data = { '_groups_': content._groups_ + [{ 'group': u'investigators', 'user': '******' }], 'observer': content.observer + [{ 'group': self.uid, 'user': '******' }], '_old_values_': old_values } view.widgets.extract = lambda *a, **kw: (data, []) view.handleApply(view, 'apply') self.assertListEqual(get_user_groups('dexter'), ['{}_observer'.format(self.uid)]) self.assertListEqual(get_user_groups('debra'), [u'investigators']) # we add/remove users data = { '_groups_': [dic for dic in content._groups_ if dic['user'] != 'debra'] + [{ 'group': u'investigators', 'user': '******' }], 'observer': [dic for dic in content.observer if dic['user'] != 'dexter'] + [{ 'group': self.uid, 'user': '******' }], '_old_values_': content._old_values_ } view.widgets.extract = lambda *a, **kw: (data, []) view.handleApply(view, 'apply') self.assertListEqual(get_user_groups('dexter'), [u'investigators']) self.assertListEqual(get_user_groups('debra'), ['{}_observer'.format(self.uid)]) # we cannot remove current user data = { '_groups_': [dic for dic in content._groups_ if dic['user'] == ''], 'observer': [dic for dic in content.observer if dic['user'] == ''], '_old_values_': content._old_values_ } view.widgets.extract = lambda *a, **kw: (data, []) self.assertRaises(Redirect, view.handleApply, view, 'apply') # we cannot handle incomplete data data = { '_groups_': content._groups_ + [{ 'group': u'investigators', 'user': None }], 'observer': content.observer, '_old_values_': content._old_values_ } view.widgets.extract = lambda *a, **kw: (data, []) self.assertRaises(Redirect, view.handleApply, view, 'apply')
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 }))
def contact_plonegroup_change(event): """Event handler when contact.plonegroup records are modified. * update workflow dms config (new groups). * invalidate vocabulary caches. * set localroles on contacts for _encodeur groups. * add a directory by organization in templates/om, templates/oem and contacts/contact-lists-folder. * set local roles on contacts, incoming-mail for group_encoder. """ if (IRecordModifiedEvent.providedBy(event) and event.record.interfaceName and event.record.interface == IContactPlonegroupConfig): registry = getUtility(IRegistry) s_orgs = get_registry_organizations() s_fcts = get_registry_functions() if not s_fcts or not s_orgs: return # we update dms config update_transitions_auc_config('dmsincomingmail') # i_e ok update_transitions_levels_config(['dmsincomingmail', 'dmsoutgoingmail', 'task']) # i_e ok # invalidate vocabularies caches invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.CreatingGroupVocabulary') invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.ActiveCreatingGroupVocabulary') invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.TreatingGroupsWithDeactivatedVocabulary') invalidate_cachekey_volatile_for('imio.dms.mail.vocabularies.TreatingGroupsForFacetedFilterVocabulary') portal = api.portal.get() # contributor on a contact can edit too for folder in (portal['outgoing-mail'], portal['contacts'], portal['contacts']['contact-lists-folder']['common']): dic = folder.__ac_local_roles__ for principal in dic.keys(): if principal.endswith('_encodeur'): del dic[principal] for uid in s_orgs: dic["%s_encodeur" % uid] = ['Contributor'] folder._p_changed = True # we add a directory by organization in templates/om om_folder = portal.templates.om oem_folder = portal.templates.oem base_model = om_folder.get('main', None) cl_folder = portal.contacts['contact-lists-folder'] for uid in s_orgs: obj = uuidToObject(uid, unrestricted=True) full_title = obj.get_full_title(separator=' - ', first_index=1) if uid not in om_folder: folder = api.content.create(container=om_folder, type='Folder', id=uid, title=full_title) # alsoProvides(folder, IActionsPanelFolderOnlyAdd) # made now in subscriber # alsoProvides(folder, INextPrevNotNavigable) roles = ['Reader'] if registry['imio.dms.mail.browser.settings.IImioDmsMailConfig.org_templates_encoder_can_edit']: roles += ['Contributor', 'Editor'] api.group.grant_roles(groupname='%s_encodeur' % uid, roles=roles, obj=folder) folder.reindexObjectSecurity() if base_model and base_model.has_been_modified(): logger.info("Copying %s in %s" % (base_model, '/'.join(folder.getPhysicalPath()))) api.content.copy(source=base_model, target=folder) if uid not in oem_folder: folder = api.content.create(container=oem_folder, type='Folder', id=uid, title=full_title) roles = ['Reader'] if registry['imio.dms.mail.browser.settings.IImioDmsMailConfig.org_email_templates_encoder_can_edit']: roles += ['Contributor', 'Editor'] api.group.grant_roles(groupname='%s_encodeur' % uid, roles=roles, obj=folder) folder.reindexObjectSecurity() # if base_model and base_model.has_been_modified(): # logger.info("Copying %s in %s" % (base_model, '/'.join(folder.getPhysicalPath()))) # api.content.copy(source=base_model, target=folder) if uid not in cl_folder: folder = api.content.create(container=cl_folder, type='Folder', id=uid, title=full_title) folder.setLayout('folder_tabular_view') roles = ['Reader', 'Contributor', 'Editor'] api.group.grant_roles(groupname='%s_encodeur' % uid, roles=roles, obj=folder) folder.reindexObjectSecurity() # we manage local roles to give needed permissions related to group_encoder options_config = {portal['incoming-mail']: ['imail_group_encoder'], portal['outgoing-mail']: ['omail_group_encoder'], portal['contacts']: ['imail_group_encoder', 'omail_group_encoder', 'contact_group_encoder'], portal['contacts']['contact-lists-folder']['common']: ['imail_group_encoder', 'omail_group_encoder', 'contact_group_encoder']} ge_config = {opt: api.portal.get_registry_record('imio.dms.mail.browser.settings.IImioDmsMailConfig.{}'.format( opt), default=False) for opt in ('imail_group_encoder', 'omail_group_encoder', 'contact_group_encoder')} group_encoder_config = [dic for dic in s_fcts if dic['fct_id'] == CREATING_GROUP_SUFFIX] # noqa F812 if group_encoder_config: orgs = group_encoder_config[0]['fct_orgs'] for folder in options_config: if any([ge_config[opt] for opt in options_config[folder]]): dic = folder.__ac_local_roles__ for principal in dic.keys(): if principal.endswith(CREATING_GROUP_SUFFIX): del dic[principal] for uid in orgs: dic["{}_{}".format(uid, CREATING_GROUP_SUFFIX)] = ['Contributor'] folder._p_changed = True
def clean_examples(self, doit='1'): """ Clean created examples """ if not check_zope_admin(): return "You must be a zope manager to run this script" if doit == '1': doit = True else: doit = False out = [] portal = api.portal.getSite() if doit: portal.portal_properties.site_properties.enable_link_integrity_checks = False registry = getUtility(IRegistry) # Delete om brains = find(unrestricted=True, portal_type='dmsoutgoingmail') for brain in brains: log_list(out, "Deleting om '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) if doit: registry['collective.dms.mailcontent.browser.settings.IDmsMailConfig.outgoingmail_number'] = 1 # Create test om params = {'title': u'Courrier test pour création de modèles (ne pas effacer)', 'internal_reference_no': internalReferenceOutgoingMailDefaultValue(DummyView(portal, portal.REQUEST)), 'mail_date': date.today(), 'mail_type': 'type1', } if doit: sub_create(portal['outgoing-mail'], 'dmsoutgoingmail', datetime.now(), 'test_creation_modele', **params) # Delete im brains = find(unrestricted=True, portal_type=['dmsincomingmail', 'dmsincoming_email']) for brain in brains: log_list(out, "Deleting im '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) if doit: registry['collective.dms.mailcontent.browser.settings.IDmsMailConfig.incomingmail_number'] = 1 # Delete own personnel pf = portal['contacts']['personnel-folder'] brains = find(unrestricted=True, context=pf, portal_type='person') for brain in brains: log_list(out, "Deleting person '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) # Deactivate own organizations ownorg = portal['contacts']['plonegroup-organization'] brains = find(unrestricted=True, context=ownorg, portal_type='organization', id=['plonegroup-organization', 'college-communal']) kept_orgs = [brain.UID for brain in brains] log_list(out, "Activating only 'college-communal'") if doit: set_registry_organizations([ownorg['college-communal'].UID()]) # Delete organization and template folders tmpl_folder = portal['templates']['om'] brains = find(unrestricted=True, context=ownorg, portal_type='organization', sort_on='path', sort_order='descending') for brain in brains: uid = brain.UID if uid in kept_orgs: continue log_list(out, "Deleting organization '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) if uid in tmpl_folder: log_list(out, "Deleting template folder '%s'" % '/'.join(tmpl_folder[uid].getPhysicalPath())) if doit: api.content.delete(obj=tmpl_folder[uid]) # Delete contacts brains = find(unrestricted=True, context=portal['contacts'], portal_type='contact_list') for brain in brains: log_list(out, "Deleting contact list '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) brains = find(unrestricted=True, context=portal['contacts'], portal_type='person', id=['jeancourant', 'sergerobinet', 'bernardlermitte']) for brain in brains: log_list(out, "Deleting person '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) brains = find(unrestricted=True, context=portal['contacts'], portal_type='organization', id=['electrabel', 'swde']) for brain in brains: log_list(out, "Deleting organization '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) # Delete users for userid in ['encodeur', 'dirg', 'chef', 'agent', 'agent1', 'lecteur']: user = api.user.get(userid=userid) for brain in find(unrestricted=True, Creator=userid, sort_on='path', sort_order='descending'): log_list(out, "Deleting object '%s' created by '%s'" % (brain.getPath(), userid)) if doit: api.content.delete(obj=brain._unrestrictedGetObject(), check_linkintegrity=False) for group in api.group.get_groups(user=user): if group.id == 'AuthenticatedUsers': continue log_list(out, "Removing user '%s' from group '%s'" % (userid, group.getProperty('title'))) if doit: api.group.remove_user(group=group, user=user) log_list(out, "Deleting user '%s'" % userid) if doit: api.user.delete(user=user) # Delete groups functions = [dic['fct_id'] for dic in get_registry_functions()] groups = api.group.get_groups() for group in groups: if '_' not in group.id or group.id in ['createurs_dossier', 'dir_general', 'lecteurs_globaux_ce', 'lecteurs_globaux_cs']: continue parts = group.id.split('_') if len(parts) == 1: continue org_uid = parts[0] function = '_'.join(parts[1:]) if org_uid in kept_orgs or function not in functions: continue log_list(out, "Deleting group '%s'" % group.getProperty('title')) if doit: api.group.delete(group=group) # Delete folders for brain in find(unrestricted=True, portal_type=('ClassificationFolder', 'ClassificationSubfolder'), sort_on='path', sort_order='descending'): log_list(out, "Deleting classification folder '%s'" % brain.getPath()) if doit: api.content.delete(obj=brain._unrestrictedGetObject()) # Delete categories caching.invalidate_cache("collective.classification.tree.utils.iterate_over_tree", portal['tree'].UID()) res = iterate_over_tree(portal['tree']) for category in reversed(res): log_list(out, "Deleting category '%s - %s'" % (safe_encode(category.identifier), safe_encode(category.title))) if doit: api.content.delete(obj=category) if doit: caching.invalidate_cache("collective.classification.tree.utils.iterate_over_tree", portal['tree'].UID()) portal.portal_properties.site_properties.enable_link_integrity_checks = True return '\n'.join(out)