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 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 __getattr__(self, name): if name not in self.form.fieldnames: return getattr(self.context, name) values = [] if name == '_old_values_': values = str(self.old_values) elif name == '_groups_': for group_id in sorted(self.form.groupids, key=self.form.groupids.get): users = api.user.get_users(groupname=group_id) for user in sorted( users, key=lambda u: u.getProperty('fullname', None) or u.id): values.append({'group': group_id, 'user': user.id}) self.old_values[name] = values else: for org in sorted(self.form.functions_orgs[name], key=methodcaller('get_full_title')): org_uid = org.UID() group_id = get_plone_group_id(org_uid, name) users = api.user.get_users(groupname=group_id) for user in sorted( users, key=lambda u: u.getProperty('fullname', None) or u.id): values.append({'group': org_uid, 'user': user.id}) self.old_values[name] = values return values
def createItemFromTemplate(self, templateUID): '''The user wants to create an item from a item template that lies in this meeting configuration. Item id is in the request.''' templateItem = uuidToObject(templateUID, unrestricted=True) # Create the new item by duplicating the template item member_id = get_current_user_id() template_path_and_title = safe_unicode( self._template_path_and_title(templateItem)) cloneEventActionLabel = translate( 'create_meeting_item_from_template_label_comments', domain='imio.history', mapping={ 'template_path_and_title': template_path_and_title, }, context=self.request) # if a proposingGroup is defined on itemTemplate and current user is creator # for this proposingGroup, we keep it keepProposingGroup = False proposingGroup = templateItem.getProposingGroup() if get_plone_group_id( proposingGroup, 'creators') in self.tool.get_plone_groups_for_user(): keepProposingGroup = True newItem = templateItem.clone( newOwnerId=member_id, cloneEventAction='create_meeting_item_from_template', cloneEventActionLabel=cloneEventActionLabel, destFolder=self.context, newPortalType=self.cfg.getItemTypeName(), keepProposingGroup=keepProposingGroup, keep_ftw_labels=True) # set _at_creation_flag to True so if user cancel first edit, it will be removed newItem._at_creation_flag = True return newItem
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 addOrModifyGroup(orga, function_id, function_title): """ create a plone group """ organization_title = orga.get_full_title(separator=' - ', first_index=1) organization_title = safe_encode(organization_title) function_title = safe_encode(function_title) group_name = get_plone_group_id(orga.UID(), function_id) group = api.group.get(groupname=group_name) group_title = '%s (%s)' % (organization_title, function_title) if group is None: group = api.group.create( groupname=group_name, title=group_title, ) notify(PlonegroupGroupCreatedEvent(group)) return True else: # group_title is maybe modified # portal_groups.editGroup(group_name, utf8) pg = api.portal.get_tool('portal_groups') if group.getProperty('title') != group_title: pg.editGroup(group_name, title=group_title) # group.setProperties(title=group_title) # not good !! return True return False
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_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 _display_asked_again_warning(advice, parent): """If advice is "asked_again" and current user is adviser for advice_group display a message explaining to change the advice_type.""" if advice.advice_type == "asked_again": advisers_group_id = get_plone_group_id(advice.advice_group, 'advisers') if parent.adviceIndex[advice.advice_group]['advice_editable']: tool = api.portal.get_tool('portal_plonemeeting') if advisers_group_id in tool.get_plone_groups_for_user(): api.portal.show_message( _("warning_advice_asked_again_need_to_change_advice_type"), request=advice.REQUEST, type="warning")
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_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 _doApply(self, data): """ """ tool = api.portal.get_tool('portal_plonemeeting') user_id = get_current_user_id() cloneEventAction = DUPLICATE_EVENT_ACTION setCurrentAsPredecessor = False manualLinkToPredecessor = False if data['keep_link']: cloneEventAction = DUPLICATE_AND_KEEP_LINK_EVENT_ACTION setCurrentAsPredecessor = True manualLinkToPredecessor = True # make sure data is correct self._check_data(data) # as passing empty keptAnnexIds/keptDecisionAnnexIds ignores it # if we unselect every annexes, we force copyAnnexes/copyDecisionAnnexes to False copyAnnexes = data['annex_ids'] and True or False copyDecisionAnnexes = data['annex_decision_ids'] and True or False # keep proposingGroup if current user creator for it keepProposingGroup = False proposingGroup = self.context.getProposingGroup() if get_plone_group_id(proposingGroup, 'creators') in tool.get_plone_groups_for_user(): keepProposingGroup = True newItem = self.context.clone( copyAnnexes=copyAnnexes, copyDecisionAnnexes=copyDecisionAnnexes, newOwnerId=user_id, cloneEventAction=cloneEventAction, keepProposingGroup=keepProposingGroup, setCurrentAsPredecessor=setCurrentAsPredecessor, manualLinkToPredecessor=manualLinkToPredecessor, keptAnnexIds=data['annex_ids'], keptDecisionAnnexIds=data['annex_decision_ids']) self.new_item_url = newItem.absolute_url() api.portal.show_message(translate('item_duplicated', domain='PloneMeeting', context=self.request), request=self.request) self._finished = True return newItem
def _display_available_items_to(self): """Check if current user profile is selected in MeetingConfig.displayAvailableItemsTo.""" displayAvailableItemsTo = self.cfg.getDisplayAvailableItemsTo() suffixes = [] groups = [] res = False cfgId = self.cfg.getId() for value in displayAvailableItemsTo: if value == 'app_users': suffixes = get_all_suffixes() elif value.startswith(POWEROBSERVERPREFIX): groups.append( get_plone_group_id(cfgId, value.split(POWEROBSERVERPREFIX)[1])) if suffixes: res = self.tool.userIsAmong(suffixes) if not res and groups: res = bool( set(groups).intersection( self.tool.get_plone_groups_for_user())) return res
def renderCell(self, item): """ """ plonegroup_organizations = get_registry_organizations() org_uid = item.UID if org_uid not in plonegroup_organizations: return "-" suffixes = get_all_suffixes(org_uid) group_ids = [ get_plone_group_id(org_uid, suffix) for suffix in suffixes ] url_group_ids = '&group_ids='.join(group_ids) # use _ for i18ndude machinery details_msg = _('Details') details_msg = translate(details_msg, context=self.request) res = u"<div id=\"group-users\" class=\"collapsible\" onclick=\"toggleDetails(" \ u"'collapsible-group-users_{0}', toggle_parent_active=false, parent_tag=null, " \ u"load_view='@@display-group-users?group_ids={1}&short:boolean={2}', base_url='{3}');\"> {4}</div>" \ u"<div id=\"collapsible-group-users_{0}\" class=\"collapsible-content\" style=\"display: none;\">" \ u"<div class=\"collapsible-inner-content\">" \ u"<img src=\"{3}/spinner_small.gif\" /></div></div>".format( org_uid, url_group_ids, self.short, self.table.portal_url, details_msg) return res
def __call__(self, group_ids, short=False): """p_groups_ids is a list of group ids. If p_group_ids is a string : - if ends with '*', it is an organization UID, we return every suffixed groups; - if a simple str, we turn it into a list.""" self.short = short self.is_manager = self._is_manager if not hasattr(group_ids, '__iter__'): if group_ids.endswith('*'): # remove ending '*' group_id = group_ids[:-1] self._check_auth(group_id) # me received a organization UID, get the Plone group ids suffixes = self._get_suffixes(group_id) group_ids = [ get_plone_group_id(group_id, suffix) for suffix in suffixes ] else: group_ids = [group_ids] self.groups = [ api.group.get(tmp_group_id) for tmp_group_id in group_ids ] return self.index()
def __call___cachekey(method, self): '''cachekey method for self.__call__.''' tool = api.portal.get_tool('portal_plonemeeting') # URL to the advice_type can change if server URL changed server_url = self.request.get('SERVER_URL', None) cfg = tool.getMeetingConfig(self.context) # when advices to add, the add advice icon is displayed # this takes PowerAdviser into account as well has_advices_to_add = self.context.getAdvicesGroupsInfosForUser( compute_to_edit=False) # confidential advices # check confidential advices if not MeetingManager isManager = tool.isManager(cfg) may_view_confidential_advices = True # bypass if no advices # but we need nevertheless to compute has_advices_to_add because # we may have no advices and no advices and power adviser may add advice advices = self.context.adviceIndex.values() isPrivacyViewable = True if advices and not isManager: isPrivacyViewable = self.context.isPrivacyViewable() if isPrivacyViewable: # if current user is a power observer that would not see the advice # we store user plone groups because a power adviser may see a confidential advice # if member of the proposingGroup user_plone_groups = tool.get_plone_groups_for_user() confidential_advices = [ advice for advice in advices if advice["isConfidential"] and not get_plone_group_id( advice["id"], "advisers") in user_plone_groups ] may_view_confidential_advices = not confidential_advices or \ not tool.isPowerObserverForCfg(cfg, power_observer_types=cfg.getAdviceConfidentialFor()) return (repr(self.context), self.context.adviceIndex._p_mtime, server_url, has_advices_to_add, isPrivacyViewable, may_view_confidential_advices)
def test_get_organization(self): suffixed_org = get_plone_group_id(self.uid, 'suffix') # get_organization may receive a plone_group_id or an organization uid self.assertEqual(get_organization(suffixed_org), self.dep1) self.assertEqual(get_organization(self.uid), self.dep1)
def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return changes = False users = {} old_values = eval(data.pop('_old_values_')) for name in old_values: try: new_value = data[ name] # If the field is not in the data, then go on to the next one except KeyError: continue new_value = set([(dic['group'], dic['user']) for dic in data[name]]) old_value = set([(dic['group'], dic['user']) for dic in old_values[name]]) if old_value == new_value: continue for action, result in (('removed', old_value - new_value), ('added', new_value - old_value)): for (group_id, user_id) in result: if group_id is None or user_id is None: required_message = _( u"There was a problem in added assignments. " u"Don't forget to complete the 2 columns! " u"You have to redo all the manipulations.") api.portal.show_message(message=required_message, request=self.request, type='error') raise Redirect(self.request.get('ACTUAL_URL')) if user_id == self.current_user_id: user_message = _( u"You cannot remove your user from a group!") api.portal.show_message(message=user_message, request=self.request, type='error') raise Redirect(self.request.get('ACTUAL_URL')) if name != '_groups_': group_id = get_plone_group_id(group_id, name) if group_id not in users: users[group_id] = [ u.id for u in api.user.get_users(groupname=group_id) ] if action == 'removed' and user_id in users[group_id]: api.group.remove_user(groupname=group_id, username=user_id) changes = True elif action == 'added' and user_id not in users[group_id]: api.group.add_user(groupname=group_id, username=user_id) changes = True if changes: api.portal.show_message(message=self.successMessage, request=self.request) else: api.portal.show_message(message=self.noChangesMessage, request=self.request, type='warn') self.request.response.redirect(self.request.get('ACTUAL_URL'))
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 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 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 test_get_plone_group_id(self): self.assertEqual(get_plone_group_id('groupuid', 'suffix'), 'groupuid_suffix')