def test_get_all_suffixes(self): self.assertEqual(get_all_suffixes(self.uid), [u'observer', u'director']) dep2_uid = self.dep2.UID() self.assertEqual(get_all_suffixes(dep2_uid), [u'observer', u'director']) self.assertEqual(get_all_suffixes(), [u'observer', u'director'])
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 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 group_deleted(event): """ Raises exception if group cannot be deleted """ group = event.principal portal = api.portal.get() request = portal.REQUEST parts = group.split('_') if len(parts) == 1: return org_uid = parts[0] group_suffix = '_'.join(parts[1:]) if org_uid in get_registry_organizations( ) and group_suffix in get_all_suffixes(org_uid): orga = api.content.find(UID=org_uid)[0].getObject() api.portal.show_message(message=_( "You cannot delete the group '${group}', linked to used organization " "'${orga}'.", mapping={ 'group': group, 'orga': safe_unicode(orga.Title()) }), request=request, type='error') raise Redirect(request.get('ACTUAL_URL'))
def __call__(self, context): all_suffixes = get_all_suffixes() terms = [] for group in api.group.get_groups(): if group.id in ('Administrators', 'Reviewers', 'Site Administrators', 'AuthenticatedUsers'): continue parts = group.id.split('_') if len(parts) > 1: group_suffix = '_'.join(parts[1:]) if group_suffix in all_suffixes: continue terms.append(SimpleTerm(group.id, title=group.getProperty('title') or group.id)) return SimpleVocabulary(terms)
def addUsers(self, org_descriptors): '''Creates Plone users and add it to linked Plone groups.''' plone_utils = self.portal.plone_utils # if we are in dev, we use DEFAULT_USER_PASSWORD, else we will generate a # password that is compliant with the current password policy... if is_develop_environment(): password = DEFAULT_USER_PASSWORD else: password = generate_password() msg = "The password used for added users is %s" % ( password or DEFAULT_USER_PASSWORD) logger.info(msg) # add a portal_message so admin adding the Plone site knows password plone_utils.addPortalMessage(msg, 'warning') member_tool = api.portal.get_tool('portal_membership') own_org = get_own_organization() plonegroup_org_uids = get_registry_organizations() for org_descr in org_descriptors: if org_descr.parent_path: # find parent organization following parent path from container container = own_org.restrictedTraverse(org_descr.parent_path) else: container = own_org org = container.get(org_descr.id) # Create users for userDescr in org_descr.getUsers(): # if we defined a generated password here above, we use it # either we use the password provided in the applied profile if password: userDescr.password = password self.addUser(userDescr) # Add users in the correct Plone groups. org_uid = org.UID() if org_uid in plonegroup_org_uids: for suffix in get_all_suffixes(org_uid): plone_group = get_plone_group(org_uid, suffix) group_members = plone_group.getMemberIds() # protect in case we have suffixes only for some groups for userDescr in getattr(org_descr, suffix, []): if userDescr.id not in group_members: api.group.add_user(group=plone_group, username=userDescr.id) if userDescr.create_member_area: member_tool.createMemberArea(userDescr.id)
def group_deleted(event): """ Raises exception if group cannot be deleted """ group = event.principal portal = api.portal.get() request = portal.REQUEST parts = group.split('_') if len(parts) == 1: return group_suffix = '_'.join(parts[1:]) registry = getUtility(IRegistry) if parts[0] in registry[ORGANIZATIONS_REGISTRY] and group_suffix in get_all_suffixes(parts[0]): orga = api.content.find(UID=parts[0])[0].getObject() api.portal.show_message(message=_("You cannot delete the group '${group}', linked to used organization " "'${orga}'.", mapping={'group': group, 'orga': safe_unicode(orga.Title())}), request=request, type='error') raise Redirect(request.get('ACTUAL_URL'))
def selectedOrganizationsPloneGroupsVocabulary(functions=[], group_title=True): """ Returns a vocabulary of selected organizations corresponding plone groups """ terms = [] # if no function given, use all functions functions = functions or get_all_suffixes() for orga_uid in get_registry_organizations(): for fct_id in functions: group_id = "%s_%s" % (orga_uid, fct_id) group = api.group.get(groupname=group_id) if group is not None: if group_title: title = group.getProperty('title') else: title = uuidToObject(orga_uid).get_full_title( separator=' - ', first_index=1) terms.append(SimpleTerm(group_id, token=group_id, title=title)) return SimpleVocabulary(terms)
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 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 _get_suffixes(self, group_id): """Make it possible to ignore some suffixes for p_group_id.""" suffixes = get_all_suffixes(group_id) return suffixes
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 _setupPoliceGroup(self): '''Configure police group. - create 'bourgmestre' group as in charge of police groups; - create police/police_compta groups; - add 'pmManager' to the _creators group; - add some default categories.''' # due to complex setup to manage college and council, # sometimes this method is called twice... if org_id_to_uid(POLICE_GROUP_PREFIX, raise_on_error=False): return self.changeUser('siteadmin') context = self.portal.portal_setup._getImportContext('Products.MeetingCharleroi:testing') initializer = ToolInitializer(context, PROJECTNAME) # create bourgmestre first as it is a group in charge of police orgs orgs, active_orgs, savedOrgsData = initializer.addOrgs([charleroi_import_data.bourg_grp]) bourg_grp = orgs[0] for org in orgs: org_uid = org.UID() self._select_organization(org_uid) # groups_in_charge are organziation ids, we need organization uids police_grp = deepcopy(charleroi_import_data.police_grp) police_grp.groups_in_charge = [org_id_to_uid(group_in_charge_id) for group_in_charge_id in police_grp.groups_in_charge] police_compta_grp = deepcopy(charleroi_import_data.police_compta_grp) police_compta_grp.groups_in_charge = [org_id_to_uid(group_in_charge_id) for group_in_charge_id in police_compta_grp.groups_in_charge] org_descriptors = (police_grp, police_compta_grp) orgs, active_orgs, savedOrgsData = initializer.addOrgs(org_descriptors, defer_data=False) for org in orgs: org_uid = org.UID() self._select_organization(org_uid) police = orgs[0] police_compta = orgs[1] gic1 = self.create('organization', id='groupincharge1', title="Group in charge 1", acronym='GIC1') gic1_uid = gic1.UID() self._select_organization(gic1.UID()) gic2 = self.create('organization', id='groupincharge2', title="Group in charge 2", acronym='GIC2') gic2_uid = gic2.UID() self._select_organization(gic2.UID()) # police is added at the end of existing groups self.assertEqual(get_organizations(the_objects=False), [self.developers_uid, self.vendors_uid, bourg_grp.UID(), police.UID(), police_compta.UID(), gic1.UID(), gic2.UID()]) # set groupsInCharge for police groups police.groups_in_charge = (gic1_uid,) police_compta.groups_in_charge = (gic1_uid,) self.vendors.groups_in_charge = (gic1_uid,) self.developers.groups_in_charge = (gic2_uid,) # make 'pmManager' able to manage everything for 'vendors' and 'police' groupsTool = self.portal.portal_groups for org in (self.vendors, police, police_compta): org_uid = org.UID() for suffix in get_all_suffixes(org_uid): groupsTool.addPrincipalToGroup('pmManager', '{0}_{1}'.format(org_uid, suffix)) self._removeConfigObjectsFor(self.meetingConfig, folders=['recurringitems', 'itemtemplates', 'categories']) self._createCategories() self._createItemTemplates()