From 99b892471a81cdf1d2c7f3952a8c1ba4d75b0f04 Mon Sep 17 00:00:00 2001 From: Timo Stollenwerk Date: Mon, 22 Dec 2014 11:04:38 +0100 Subject: [PATCH] Remove the users/groups control panel (moved to Products.CMFPlone). --- CHANGES.rst | 3 + plone/app/controlpanel/configure.zcml | 49 -- plone/app/controlpanel/tests/test_doctests.py | 10 +- plone/app/controlpanel/tests/usergroups.txt | 378 --------- plone/app/controlpanel/usergroups.py | 779 ------------------ .../controlpanel/usergroups_groupdetails.pt | 254 ------ .../usergroups_groupmembership.pt | 345 -------- .../controlpanel/usergroups_groupsoverview.pt | 281 ------- .../controlpanel/usergroups_usermembership.pt | 225 ----- .../controlpanel/usergroups_usersoverview.pt | 253 ------ plone/app/controlpanel/usergroupssettings.pt | 58 -- 11 files changed, 8 insertions(+), 2627 deletions(-) delete mode 100644 plone/app/controlpanel/tests/usergroups.txt delete mode 100644 plone/app/controlpanel/usergroups.py delete mode 100644 plone/app/controlpanel/usergroups_groupdetails.pt delete mode 100644 plone/app/controlpanel/usergroups_groupmembership.pt delete mode 100644 plone/app/controlpanel/usergroups_groupsoverview.pt delete mode 100644 plone/app/controlpanel/usergroups_usermembership.pt delete mode 100644 plone/app/controlpanel/usergroups_usersoverview.pt delete mode 100644 plone/app/controlpanel/usergroupssettings.pt diff --git a/CHANGES.rst b/CHANGES.rst index 2d36f21..2e55a15 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog 3.0.0 (unreleased) ------------------ +- Remove the users/groups control panel (moved to Products.CMFPlone). + [timo] + - Remove the markup control panel, as it was moved to Products.CMFPlone. [thet] diff --git a/plone/app/controlpanel/configure.zcml b/plone/app/controlpanel/configure.zcml index 64089a0..c53cde4 100644 --- a/plone/app/controlpanel/configure.zcml +++ b/plone/app/controlpanel/configure.zcml @@ -15,8 +15,6 @@ - - - - - - - - - - - - - - >> self.loginAsManager() - >>> config_url = 'http://nohost/plone/plone_control_panel' - - >>> self.browser.open(config_url) - >>> self.browser.getLink('Users and Groups').click() - >>> '@@usergroup-userprefs' in self.browser.url - True - -With the 'many users' flag disabled, should allow us to see the 'show all' button. - >>> 'Show all' in self.browser.contents - True - -So let's try a search, first on name... - >>> self.browser.getControl(name='searchstring').value = 'Richard' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Richard Ramirez' in self.browser.contents - True - >>> 'Sara Richardson' in self.browser.contents - True - >>> 'Émilie Richard' in self.browser.contents - True - -Try a search with an accent... - >>> self.browser.getControl(name='searchstring').value = 'Émilie' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Émilie Richard' in self.browser.contents - True - -And now on userid... - >>> self.browser.getControl(name='searchstring').value = 'TWrMCLIo' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Autumn Brooks' in self.browser.contents - True - -And now on email address.. - >>> self.browser.getControl(name='searchstring').value = 'gracie@' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Gracie Adams' in self.browser.contents - True - -Make some modifications to Gracie's roles... - >>> self.browser.getControl(name='users.roles:list:records').getControl(value='Contributor').selected - False - >>> self.browser.getControl(name='users.roles:list:records').getControl(value='Contributor').selected = True - >>> self.browser.getControl(name='form.button.Modify').click() - -The previous search should still be in effect... - >>> self.browser.getControl(name='searchstring').value - 'gracie@' - -But values should be changed - >>> self.browser.getControl(name='users.roles:list:records').getControl(value='Contributor').selected - True - -We'll reset her password. - >>> self.browser.getControl(name='users.resetpassword:records').value = True - >>> self.browser.getControl(name='form.button.Modify').click() - -Whoops, we haven't set up our mailhost... - >>> 'No mailhost defined. Unable to reset passwords.' in self.browser.contents - True - -# Mailhost is failing in this testcase, so commenting this bit out for now. -# Let's do that and try again. -# >>> self.browser.open('http://nohost/plone/@@mail-controlpanel') -# >>> self.browser.getControl('SMTP server').value = 'nohost' -# >>> self.browser.getControl("Site 'From' address").value = 'bob@example.com' -# >>> self.browser.getControl('Save').click() -# >>> self.browser.getLink('Users and Groups').click() -# >>> self.browser.getControl(name='searchstring').value = 'gracie@' -# >>> self.browser.getControl(name='form.button.Search').click() -# >>> 'Gracie Adams' in self.browser.contents -# True -# >>> self.browser.getControl(name='users.resetpassword:records').value = True -# >>> self.browser.getControl(name='form.button.Modify').click() -# >>> 'No mailhost defined. Unable to reset passwords.' in self.browser.contents -# False - -Let's try deleting Gracie. - >>> self.browser.getControl(name='searchstring').value = 'gracie@' - >>> self.browser.getControl(name='form.button.Search').click() - >>> self.browser.getControl(name='delete:list').getControl(value='RwAO2YPa').selected = True - >>> self.browser.getControl(name='form.button.Modify').click() - -The previous search should still be in effect... - >>> self.browser.getControl(name='searchstring').value - 'gracie@' - -But the user Gracie Adams should now be gone. - >>> 'Gracie Adams' in self.browser.contents - False - -Turning on the 'many users' flag should remove the 'Search All' button. - >>> self.browser.getLink('Settings').click() - >>> self.browser.getControl(name='form.many_users').value = True - >>> self.browser.getControl('Save').click() - -Go directly to the userprefs panel (getting link "Users" results in a trip to the Members folder). - >>> self.browser.open('http://nohost/plone/@@usergroup-userprefs') - >>> 'Show All' in self.browser.contents - False - -An empty search string while 'many users' is enabled should not perform a search. - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Enter a username to search for' in self.browser.contents - True - -Go directly to the groupprefs panel (getting link "Groups" results in a trip to the "users and groups" link). - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - -With the 'many groups' flag disabled, should allow us to see the 'show all' button. - >>> 'Show all' in self.browser.contents - True - -We'll attempt a search... - >>> self.browser.getControl(name='searchstring').value = 'group3' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Group 3' in self.browser.contents - True - -And again with the group's title - >>> self.browser.getControl(name='searchstring').value = 'Group 3 accentu\xc3\xa9' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'group3' in self.browser.contents - True - -Add a new role - >>> self.browser.getControl(name='group_group3:list', index=1).getControl(value='Contributor').selected - False - >>> self.browser.getControl(name='group_group3:list', index=1).getControl(value='Contributor').selected = True - >>> self.browser.getControl('Apply Changes').click() - >>> self.browser.getControl(name='group_group3:list', index=1).getControl(value='Contributor').selected - True - -And remove it again... - >>> self.browser.getControl(name='group_group3:list', index=1).getControl(value='Contributor').selected = False - >>> self.browser.getControl('Apply Changes').click() - >>> self.browser.getControl(name='group_group3:list', index=1).getControl(value='Contributor').selected - False - -Delete a group... - >>> self.browser.getControl(name='delete:list').getControl(value='group3').selected = True - >>> self.browser.getControl(name='form.button.Modify').click() - >>> self.browser.getControl(name='searchstring').value - 'Group 3 accentu\xc3\xa9' - >>> 'group3' in self.browser.contents - False - -Turning on the 'many groups' flag should remove the 'Search All' button. - >>> self.browser.getLink('Settings').click() - >>> self.browser.getControl(name='form.many_groups').value = True - >>> self.browser.getControl('Save').click() - >>> self.browser.getLink('Groups').click() - >>> 'Search All' in self.browser.contents - False - -An empty search string while 'many groups' is enabled should not perform a search. - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Group name' in self.browser.contents - False - -Now let's try to break things. -Add a test for http://dev.plone.org/plone/ticket/8940: -"Group roles show up on the user roles page for members of that group." - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getControl(name='searchstring').value = 'Reviewers' - >>> self.browser.getControl(name='form.button.Search').click() - >>> self.browser.getControl(name='group_Reviewers:list', index=1).getControl(value='Reader').selected = True - >>> self.browser.getControl('Apply Changes').click() - >>> self.browser.getLink('Reviewers').click() - >>> self.browser.getLink('Group Members').click() - >>> self.browser.getControl(name='searchstring').value = 'Sean Foster' - >>> self.browser.getControl(name='form.button.Search').click() - >>> self.browser.getControl(name='add:list').getControl(value='SLUhquYa').selected = True - >>> self.browser.getControl(name='form.button.Add').click() - >>> self.browser.open('http://nohost/plone/@@usergroup-userprefs') - >>> self.browser.getControl(name='searchstring').value = 'Sean Foster' - >>> self.browser.getControl(name='form.button.Search').click() - -#So according to the ticket, this should fail, finding a checked checkbox instead of an "inherited" icon -# >>> self.browser.getControl(name='users.roles:list:records').getControl(value='Reader').selected -# Traceback (most recent call last): -# ... -# LookupError: value 'Reader' - -And then making some change to the user and saving it will assign that checked role directly to the user... - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getControl(name='searchstring').value = 'Authenticated' - >>> self.browser.getControl(name='form.button.Search').click() - >>> self.browser.getControl(name='group_AuthenticatedUsers:list', index=1).getControl(value='Editor').selected = False - >>> self.browser.getControl('Apply Changes').click() - >>> self.browser.open('http://nohost/plone/@@usergroup-userprefs') - >>> self.browser.getControl(name='searchstring').value = 'Sean Foster' - >>> self.browser.getControl(name='form.button.Search').click() - -According to the ticket, the user will now have an assigned role of 'Editor', which should not be the case. - >>> self.browser.getControl(name='users.roles:list:records').getControl(value='Editor').selected - False - -Turn off the many groups/users flags again - >>> self.browser.getLink('Settings').click() - >>> self.browser.getControl(name='form.many_groups').value = False - >>> self.browser.getControl(name='form.many_users').value = False - >>> self.browser.getControl('Save').click() - -Now let's try modifying some group memberships... - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getLink('Group 1 (group1)').click() - >>> 'There is no group or user attached to this group.' in self.browser.contents - True - -Make sure that providing a search string while hitting 'show all' does not search for just that term. - >>> self.browser.getControl(name='searchstring').value = 'management' - >>> self.browser.getControl(name='form.button.FindAll').click() - >>> 'No matches' in self.browser.contents - False - >>> 'Brian Simmons' in self.browser.contents - True - >>> self.browser.getControl(name='searchstring').value is '' - True - -# Now provide a term and do a search. -# >>> self.browser.getControl(name='searchstring').value = 'management' -# >>> self.browser.getControl(name='form.button.Search').click() -# >>> 'No matches' in self.browser.contents -# False -# >>> 'Management' in self.browser.contents -# True -# >>> 'Brian Simmons' in self.browser.contents -# False - -Check to make sure search results are ordered properly and display the title/fullname and id - >>> self.browser.getControl(name='form.button.FindAll').click() - >>> self.browser.contents - '...Search for new group members... - ...Abigail Simmons...(XYsmd7ux)... - ...Alexandra Nelson...(FElYwiIr)... - ...Blake Jenkins...(BlXLQh7r)...' - -Add some group members - >>> self.browser.getControl(name='add:list').getControl(value='XYsmd7ux').selected = True - >>> self.browser.getControl(name='add:list').getControl(value='BlXLQh7r').selected = True - >>> self.browser.getControl(name='form.button.Add').click() - -These should be displayed in the Current group members section now. - >>> self.browser.contents - '...Current group members... - ...Abigail Simmons...(XYsmd7ux)... - ...Blake Jenkins...(BlXLQh7r)... - ...Search for new group members...' - -Users/Groups can be removed from this list as well. - >>> self.browser.getControl(name='delete:list').getControl(value='XYsmd7ux').selected = True - >>> self.browser.getControl(name='form.button.Edit').click() - >>> 'Changes made' in self.browser.contents - True - >>> 'Abigail Simmons' in self.browser.contents - False - -Open the groups overview, make sure Group 1 and Group 2 don't have globally-assigned roles - >>> self.browser.getLink('Group Members').click() - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getControl(name='group_group1:list', index=1).getControl(value='Contributor').selected - False - >>> self.browser.getControl(name='group_group2:list', index=1).getControl(value='Contributor').selected - False - -Give the Group 1 group the contributor role - >>> self.browser.getControl(name='group_group1:list', index=1).getControl(value='Contributor').selected = True - >>> self.browser.getControl('Apply Changes').click() - -Now Group 1 should show the global contributor role - >>> self.browser.getControl(name='group_group1:list', index=1).getControl(value='Contributor').selected - True - -Let's try adding groups to a user. -Go directly to the Users Overview screen. - >>> self.browser.open('http://nohost/plone/@@usergroup-userprefs') - >>> self.browser.getControl(name='searchstring').value = 'Sofia' - >>> self.browser.getControl(name='form.button.Search').click() - >>> 'Sofia Williams' in self.browser.contents - True - >>> self.browser.getLink('Sofia Williams').click() - >>> self.browser.getLink('Group Memberships').click() - >>> '@@usergroup-usermembership?userid=tyOxRnml' in self.browser.url - True - >>> self.browser.contents - '...Group memberships for...Sofia Williams...(tyOxRnml)... - ...Current group memberships... - ...Authenticated Users... - ...Assign to groups... - ...Administrators... - ...Group 1... - ...Group 2... - ...Reviewers...' - >>> self.browser.getControl(name='add:list').getControl(value='group2').selected = True - >>> self.browser.getControl(name='form.button.Add').click() - >>> '@@usergroup-usermembership?userid=tyOxRnml' in self.browser.url - True - >>> self.browser.contents - '...Group memberships for...Sofia Williams...(tyOxRnml)... - ...Current group memberships... - ...Authenticated Users... - ...Group 2... - ...Assign to groups... - ...Administrators... - ...Group 1... - ...Reviewers...' - -Check to make sure search results are ordered properly and display the title/fullname and id - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getLink('Group 1 (group1)').click() - >>> self.browser.getControl(name='form.button.FindAll').click() - >>> self.browser.contents - '...Current group members... - ...Blake Jenkins...(BlXLQh7r)... - ...Search for new group members... - ...Administrators...(Administrators)... - ...Group 2...(group2)... - ...Reviewers...(Reviewers)... - ...Abigail Simmons...(XYsmd7ux)... - ...Alexandra Nelson...(FElYwiIr)...' - -Add some group members - >>> self.browser.getControl(name='add:list').getControl(value='group2').selected = True - >>> self.browser.getControl(name='add:list').getControl(value='Reviewers').selected = True - >>> self.browser.getControl(name='add:list').getControl(value='XYsmd7ux').selected = True - >>> self.browser.getControl(name='form.button.Add').click() - -These should be displayed in the Current group members section now. - >>> self.browser.contents - '...Current group members... - ...Group 2...(group2)... - ...Reviewers...(Reviewers)... - ...Abigail Simmons...(XYsmd7ux)... - ...Blake Jenkins...(BlXLQh7r)... - ...Search for new group members...' - -Users/Groups they can be removed from this list as well. - >>> self.browser.getControl(name='delete:list').getControl(value='XYsmd7ux').selected = True - >>> self.browser.getControl(name='form.button.Edit').click() - >>> 'Changes made' in self.browser.contents - True - >>> 'Abigail Simmons' in self.browser.contents - False - -Groups nested within groups assigned to this one should not be displayed - >>> self.browser.getLink('Group 2').click() - >>> self.browser.getLink('Group Members').click() - -Open the groups overview, make sure Group 2 doesn't have a globally-assigned contributor role - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getControl(name='group_group1:list', index=1).getControl(value='Contributor').selected - True - >>> self.browser.getControl(name='group_group2:list', index=1).getControl(value='Contributor').selected - Traceback (most recent call last): - ... - LookupError: value 'Contributor' - -But the nested group (Group 2) should show it as an inherited global role - >>> self.browser.getControl(name='group_group2:list', index=1).getControl(value='Contributor') - Traceback (most recent call last): - ... - LookupError: value 'Contributor' - -Even when explicitly giving the nested group (Group 2) the contributor role, -it should still show it as an inherited global role. - >>> self.portal.portal_groups.editGroup('group2', roles=['Contributor'], groups=()) - >>> self.browser.open('http://nohost/plone/@@usergroup-groupprefs') - >>> self.browser.getControl(name='group_group2:list', index=1).getControl(value='Contributor') - Traceback (most recent call last): - ... - LookupError: value 'Contributor' diff --git a/plone/app/controlpanel/usergroups.py b/plone/app/controlpanel/usergroups.py deleted file mode 100644 index 9efafe2..0000000 --- a/plone/app/controlpanel/usergroups.py +++ /dev/null @@ -1,779 +0,0 @@ -import logging -from smtplib import SMTPException - -from AccessControl import getSecurityManager -from Acquisition import aq_inner -from zExceptions import Forbidden -from itertools import chain - -from zope.interface import Interface -from zope.component import adapts, getAdapter, getMultiAdapter, getUtility -from zope.formlib.form import FormFields -from zope.interface import implements -from zope.schema import Bool -from ZTUtils import make_query - -from plone.protect import CheckAuthenticator -from Products.CMFCore.interfaces import ISiteRoot -from Products.CMFCore.permissions import ManagePortal -from Products.CMFCore.utils import getToolByName -from Products.CMFDefault.formlib.schema import ProxyFieldProperty -from Products.CMFDefault.formlib.schema import SchemaAdapterBase -from Products.CMFPlone import PloneMessageFactory as _ -from Products.CMFPlone.utils import normalizeString -from Products.CMFPlone.interfaces import IPloneSiteRoot -from Products.statusmessages.interfaces import IStatusMessage -from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile -from Products.PluggableAuthService.interfaces.plugins import IRolesPlugin - -from form import ControlPanelForm, ControlPanelView -from Products.CMFPlone.interfaces import ISecuritySchema - -logger = logging.getLogger('plone.app.controlpanel') - - -class IUserGroupsSettingsSchema(Interface): - - many_groups = Bool(title=_(u'Many groups?'), - description=_(u"Determines if your Plone is optimized " - "for small or large sites. In environments with a " - "lot of groups it can be very slow or impossible " - "to build a list all groups. This option tunes the " - "user interface and behaviour of Plone for this " - "case by allowing you to search for groups instead " - "of listing all of them."), - default=False) - - many_users = Bool(title=_(u'Many users?'), - description=_(u"Determines if your Plone is optimized " - "for small or large sites. In environments with a " - "lot of users it can be very slow or impossible to " - "build a list all users. This option tunes the user " - "interface and behaviour of Plone for this case by " - "allowing you to search for users instead of " - "listing all of them."), - default=False) - -class UserGroupsSettingsControlPanelAdapter(SchemaAdapterBase): - - adapts(IPloneSiteRoot) - implements(IUserGroupsSettingsSchema) - - def __init__(self, context): - super(UserGroupsSettingsControlPanelAdapter, self).__init__(context) - pprop = getToolByName(context, 'portal_properties') - self.context = pprop.site_properties - - many_groups = ProxyFieldProperty(IUserGroupsSettingsSchema['many_groups']) - many_users = ProxyFieldProperty(IUserGroupsSettingsSchema['many_users']) - -class UserGroupsSettingsControlPanel(ControlPanelForm): - - base_template = ControlPanelForm.template - template = ZopeTwoPageTemplateFile('usergroupssettings.pt') - - form_fields = FormFields(IUserGroupsSettingsSchema) - - label = _("User/Groups settings") - description = _("User and groups settings for this site.") - form_name = _("User/Groups settings") - -class UsersGroupsControlPanelView(ControlPanelView): - - @property - def portal_roles(self): - pmemb = getToolByName(aq_inner(self.context), 'portal_membership') - return [r for r in pmemb.getPortalRoles() if r != 'Owner'] - - @property - def many_users(self): - pprop = getToolByName(aq_inner(self.context), 'portal_properties') - return pprop.site_properties.many_users - - @property - def many_groups(self): - pprop = getToolByName(aq_inner(self.context), 'portal_properties') - return pprop.site_properties.many_groups - - @property - def email_as_username(self): - return getAdapter(aq_inner(self.context), ISecuritySchema).get_use_email_as_login() - - def makeQuery(self, **kw): - return make_query(**kw) - - def membershipSearch(self, searchString='', searchUsers=True, searchGroups=True, ignore=None): - """Search for users and/or groups, returning actual member and group items - Replaces the now-deprecated prefs_user_groups_search.py script""" - if ignore is None: - ignore = [] - groupResults = userResults = [] - - gtool = getToolByName(self, 'portal_groups') - mtool = getToolByName(self, 'portal_membership') - - searchView = getMultiAdapter((aq_inner(self.context), self.request), name='pas_search') - - if searchGroups: - groupResults = searchView.merge(chain(*[searchView.searchGroups(**{field: searchString}) for field in ['id', 'title']]), 'groupid') - groupResults = [gtool.getGroupById(g['id']) for g in groupResults if g['id'] not in ignore] - groupResults.sort(key=lambda x: x is not None and normalizeString(x.getGroupTitleOrName())) - - if searchUsers: - userResults = searchView.merge(chain(*[searchView.searchUsers(**{field: searchString}) for field in ['name', 'fullname', 'email']]), 'userid') - userResults = [mtool.getMemberById(u['id']) for u in userResults if u['id'] not in ignore] - userResults.sort(key=lambda x: x is not None and x.getProperty('fullname') is not None and normalizeString(x.getProperty('fullname')) or '') - - return groupResults + userResults - - def atoi(self, s): - try: - return int(s) - except ValueError: - return 0 - - @property - def is_zope_manager(self): - return getSecurityManager().checkPermission(ManagePortal, self.context) - - # The next two class methods implement the following truth table: - # - # MANY USERS/GROUPS SEARCHING CAN LIST USERS/GROUPS RESULT - # False False False Lists unavailable - # False False True Show all - # False True False Show matching - # False True True Show matching - # True False False Too many to list - # True False True Lists unavailable - # True True False Show matching - # True True True Show matching - - # TODO: Maybe have these methods return a text message (instead of a bool) - # corresponding to the actual result, e.g. "Too many to list", "Lists unavailable" - - @property - def show_group_listing_warning(self): - if not self.searchString: - acl = getToolByName(self, 'acl_users') - if acl.canListAllGroups(): - if self.many_groups: - return True - return False - - @property - def show_users_listing_warning(self): - if not self.searchString: - acl = getToolByName(self, 'acl_users') - # XXX Huh? Is canListAllUsers broken? - if not acl.canListAllUsers(): - if self.many_users: - return True - return False - - -class UsersOverviewControlPanel(UsersGroupsControlPanelView): - - mailhost_tool = None - - def __call__(self): - form = self.request.form - submitted = form.get('form.submitted', False) - search = form.get('form.button.Search', None) is not None - findAll = form.get('form.button.FindAll', None) is not None - self.searchString = not findAll and form.get('searchstring', '') or '' - self.searchResults = [] - self.newSearch = False - - if search or findAll: - self.newSearch = True - - if submitted: - if form.get('form.button.Modify', None) is not None: - self.manageUser(form.get('users', None), - form.get('resetpassword', []), - form.get('delete', [])) - - # Only search for all ('') if the many_users flag is not set. - if not(self.many_users) or bool(self.searchString): - self.searchResults = self.doSearch(self.searchString) - - return self.index() - - def get_mailhost(self): - if self.mailhost_tool is None: - self.mailhost_tool = getToolByName(self, 'MailHost') - return self.mailhost_tool - - def doSearch(self, searchString): - - acl = getToolByName(self, 'acl_users') - rolemakers = acl.plugins.listPlugins(IRolesPlugin) - - mtool = getToolByName(self, 'portal_membership') - searchView = getMultiAdapter((aq_inner(self.context), self.request), name='pas_search') - - # First, search for all inherited roles assigned to each group. - # We push this in the request so that IRoles plugins are told provide - # the roles inherited from the groups to which the principal belongs. - self.request.set('__ignore_group_roles__', False) - self.request.set('__ignore_direct_roles__', True) - inheritance_enabled_users = searchView.merge(chain(*[searchView.searchUsers(**{field: searchString}) for field in ['name', 'fullname', 'email']]), 'userid') - allInheritedRoles = {} - for user_info in inheritance_enabled_users: - userId = user_info['id'] - user = acl.getUserById(userId) - # play safe, though this should never happen - if user is None: - logger.warn('Skipped user without principal object: %s' % userId) - continue - allAssignedRoles = [] - for rolemaker_id, rolemaker in rolemakers: - # getRolesForPrincipal can return None - roles = rolemaker.getRolesForPrincipal(user) or () - allAssignedRoles.extend(roles) - allInheritedRoles[userId] = allAssignedRoles - - # We push this in the request such IRoles plugins don't provide - # the roles from the groups the principal belongs. - self.request.set('__ignore_group_roles__', True) - self.request.set('__ignore_direct_roles__', False) - explicit_users = searchView.merge(chain(*[searchView.searchUsers(**{field: searchString}) for field in ['login', 'fullname', 'email']]), 'userid') - - # Tack on some extra data, including whether each role is explicitly - # assigned ('explicit'), inherited ('inherited'), or not assigned at all (None). - results = [] - - for user_info in explicit_users: - userId = user_info['id'] - user = mtool.getMemberById(userId) - # play safe, though this should never happen - if user is None: - logger.warn('Skipped user without principal object: %s' % userId) - continue - explicitlyAssignedRoles = [] - for rolemaker_id, rolemaker in rolemakers: - # getRolesForPrincipal can return None - roles = rolemaker.getRolesForPrincipal(user) or () - explicitlyAssignedRoles.extend(roles) - - roleList = {} - for role in self.portal_roles: - canAssign = user.canAssignRole(role) - if role == 'Manager' and not self.is_zope_manager: - canAssign = False - roleList[role]={'canAssign': canAssign, - 'explicit': role in explicitlyAssignedRoles, - 'inherited': role in allInheritedRoles.get(userId, [])} - - canDelete = user.canDelete() - canPasswordSet = user.canPasswordSet() - if ('Manager' in explicitlyAssignedRoles or - 'Manager' in allInheritedRoles.get(userId, [])): - if not self.is_zope_manager: - canDelete = False - canPasswordSet = False - - user_info['roles'] = roleList - user_info['login'] = user.getUserName() - user_info['fullname'] = user.getProperty('fullname', '') - user_info['email'] = user.getProperty('email', '') - user_info['can_delete'] = canDelete - user_info['can_set_email'] = user.canWriteProperty('email') - user_info['can_set_password'] = canPasswordSet - results.append(user_info) - - # Sort the users by fullname - results.sort(key=lambda x: x is not None and x['fullname'] is not None and normalizeString(x['fullname']) or '') - - # Reset the request variable, just in case. - self.request.set('__ignore_group_roles__', False) - return results - - def manageUser(self, users=None, resetpassword=None, delete=None): - if users is None: - users = [] - if resetpassword is None: - resetpassword = [] - if delete is None: - delete = [] - - CheckAuthenticator(self.request) - - if users: - context = aq_inner(self.context) - acl_users = getToolByName(context, 'acl_users') - mtool = getToolByName(context, 'portal_membership') - regtool = getToolByName(context, 'portal_registration') - groups_tool = getToolByName(self, 'portal_groups') - - utils = getToolByName(context, 'plone_utils') - - users_with_reset_passwords = [] - users_failed_reset_passwords = [] - - for user in users: - # Don't bother if the user will be deleted anyway - if user.id in delete: - continue - - member = mtool.getMemberById(user.id) - current_roles = member.getRoles() - - # TODO: is it still possible to change the e-mail address here? - # isn't that done on @@user-information now? - # If email address was changed, set the new one - if hasattr(user, 'email'): - # If the email field was disabled (ie: non-writeable), the - # property might not exist. - if user.email != member.getProperty('email'): - utils.setMemberProperties(member, REQUEST=context.REQUEST, email=user.email) - utils.addPortalMessage(_(u'Changes applied.')) - - # If reset password has been checked email user a new password - pw = None - if hasattr(user, 'resetpassword'): - if 'Manager' in current_roles and not self.is_zope_manager: - raise Forbidden - if not context.unrestrictedTraverse('@@overview-controlpanel').mailhost_warning(): - pw = regtool.generatePassword() - else: - utils.addPortalMessage(_(u'No mailhost defined. Unable to reset passwords.'), type='error') - - roles = user.get('roles', []) - if not self.is_zope_manager: - # don't allow adding or removing the Manager role - # add check if user is in Administrators group - grouproles = [] - for group in groups_tool.getGroupsByUserId(member.id): - grouproles.extend(group.getRoles()) - if ('Manager' in roles or 'Manager' in grouproles) != ('Manager' in current_roles): - raise Forbidden - - # Ideally, we would like to detect if any role assignment has - # actually changed, and only then issue "Changes applied". - acl_users.userFolderEditUser(user.id, pw, roles, member.getDomains(), REQUEST=context.REQUEST) - - if pw: - context.REQUEST.form['new_password'] = pw - # [Comment copied from plone.app.contentrules.actions.mail.MailActionExecutor.__call__()] - # XXX: We're using "immediate=True" because otherwise we won't - # be able to catch SMTPException as the smtp connection is made - # as part of the transaction apparatus. - # AlecM thinks this wouldn't be a problem if mail queuing was - # always on -- but it isn't. (stevem) - # so we test if queue is not on to set immediate - immediate = not self.get_mailhost().smtp_queue - try: - regtool.mailPassword(user.id, context.REQUEST, immediate=immediate) - except SMTPException as e: - logger.exception(e) - users_failed_reset_passwords.append(user.id) - else: - users_with_reset_passwords.append(user.id) - - if delete: - self.deleteMembers(delete) - - if users_with_reset_passwords: - reset_passwords_message = _( - u"reset_passwords_msg", - default=u"The following users have been sent an e-mail with link to reset their password: ${user_ids}", - mapping={ - u"user_ids" : ', '.join(users_with_reset_passwords), - }, - ) - utils.addPortalMessage(reset_passwords_message) - if users_failed_reset_passwords: - failed_passwords_message = _( - u'failed_passwords_msg', - default=u'A password reset e-mail could not be sent to the following users: ${user_ids}', - mapping={ - u'user_ids' : ', '.join(users_failed_reset_passwords), - }, - ) - utils.addPortalMessage(failed_passwords_message, type='error') - - # TODO: issue message only if something actually has changed - utils.addPortalMessage(_(u'Changes applied.')) - - def deleteMembers(self, member_ids): - # this method exists to bypass the 'Manage Users' permission check - # in the CMF member tool's version - context = aq_inner(self.context) - mtool = getToolByName(self.context, 'portal_membership') - - # Delete members in acl_users. - acl_users = context.acl_users - if isinstance(member_ids, basestring): - member_ids = (member_ids,) - member_ids = list(member_ids) - for member_id in member_ids[:]: - member = mtool.getMemberById(member_id) - if member is None: - member_ids.remove(member_id) - else: - if not member.canDelete(): - raise Forbidden - if 'Manager' in member.getRoles() and not self.is_zope_manager: - raise Forbidden - try: - acl_users.userFolderDelUsers(member_ids) - except (AttributeError, NotImplementedError): - raise NotImplementedError('The underlying User Folder ' - 'doesn\'t support deleting members.') - - # Delete member data in portal_memberdata. - mdtool = getToolByName(context, 'portal_memberdata', None) - if mdtool is not None: - for member_id in member_ids: - mdtool.deleteMemberData(member_id) - - # Delete members' local roles. - mtool.deleteLocalRoles( getUtility(ISiteRoot), member_ids, - reindex=1, recursive=1 ) - - -class GroupDetailsControlPanel(UsersGroupsControlPanelView): - - def __call__(self): - context = aq_inner(self.context) - - self.gtool = getToolByName(context, 'portal_groups') - self.gdtool = getToolByName(context, 'portal_groupdata') - self.regtool = getToolByName(context, 'portal_registration') - self.groupname = getattr(self.request, 'groupname', None) - self.grouproles = self.request.set('grouproles', []) - self.group = self.gtool.getGroupById(self.groupname) - self.grouptitle = self.groupname - if self.group is not None: - self.grouptitle = self.group.getGroupTitleOrName() - - self.request.set('grouproles', self.group.getRoles() if self.group else []) - - submitted = self.request.form.get('form.submitted', False) - if submitted: - CheckAuthenticator(self.request) - - msg = _(u'No changes made.') - self.group = None - - title = self.request.form.get('title', None) - description = self.request.form.get('description', None) - addname = self.request.form.get('addname', None) - - if addname: - if not self.regtool.isMemberIdAllowed(addname): - msg = _(u'The group name you entered is not valid.') - IStatusMessage(self.request).add(msg, 'error') - return self.index() - - success = self.gtool.addGroup(addname, (), (), title=title, - description=description, - REQUEST=self.request) - if not success: - msg = _(u'Could not add group ${name}, perhaps a user or group with ' - u'this name already exists.', mapping={u'name' : addname}) - IStatusMessage(self.request).add(msg, 'error') - return self.index() - - self.group = self.gtool.getGroupById(addname) - msg = _(u'Group ${name} has been added.', - mapping={u'name' : addname}) - - elif self.groupname: - self.gtool.editGroup(self.groupname, roles=None, groups=None, - title=title, description=description, - REQUEST=context.REQUEST) - self.group = self.gtool.getGroupById(self.groupname) - msg = _(u'Changes saved.') - - else: - msg = _(u'Group name required.') - - processed = {} - for id, property in self.gdtool.propertyItems(): - processed[id] = self.request.get(id, None) - - if self.group: - # for what reason ever, the very first group created does not exist - self.group.setGroupProperties(processed) - - IStatusMessage(self.request).add(msg, type=self.group and 'info' or 'error') - if self.group and not self.groupname: - target_url = '%s/%s' % (self.context.absolute_url(), '@@usergroup-groupprefs') - self.request.response.redirect(target_url) - return '' - - return self.index() - - -class GroupsOverviewControlPanel(UsersGroupsControlPanelView): - - def __call__(self): - form = self.request.form - submitted = form.get('form.submitted', False) - search = form.get('form.button.Search', None) is not None - findAll = form.get('form.button.FindAll', None) is not None - self.searchString = not findAll and form.get('searchstring', '') or '' - self.searchResults = [] - self.newSearch = False - - if search or findAll: - self.newSearch = True - - if submitted: - if form.get('form.button.Modify', None) is not None: - self.manageGroup([group[len('group_'):] for group in self.request.keys() if group.startswith('group_')], - form.get('delete', [])) - - # Only search for all ('') if the many_users flag is not set. - if not(self.many_groups) or bool(self.searchString): - self.searchResults = self.doSearch(self.searchString) - - return self.index() - - def doSearch(self, searchString): - """ Search for a group by id or title""" - acl = getToolByName(self, 'acl_users') - rolemakers = acl.plugins.listPlugins(IRolesPlugin) - - searchView = getMultiAdapter((aq_inner(self.context), self.request), name='pas_search') - - # First, search for inherited roles assigned to each group. - # We push this in the request so that IRoles plugins are told provide - # the roles inherited from the groups to which the principal belongs. - self.request.set('__ignore_group_roles__', False) - self.request.set('__ignore_direct_roles__', True) - inheritance_enabled_groups = searchView.merge(chain(*[searchView.searchGroups(**{field: searchString}) for field in ['id', 'title']]), 'id') - allInheritedRoles = {} - for group_info in inheritance_enabled_groups: - groupId = group_info['id'] - group = acl.getGroupById(groupId) - group_info['title'] = group.getProperty('title', group_info['title']) - allAssignedRoles = [] - for rolemaker_id, rolemaker in rolemakers: - # getRolesForPrincipal can return None - roles = rolemaker.getRolesForPrincipal(group) or () - allAssignedRoles.extend(roles) - allInheritedRoles[groupId] = allAssignedRoles - - # Now, search for all roles explicitly assigned to each group. - # We push this in the request so that IRoles plugins don't provide - # the roles inherited from the groups to which the principal belongs. - self.request.set('__ignore_group_roles__', True) - self.request.set('__ignore_direct_roles__', False) - explicit_groups = searchView.merge(chain(*[searchView.searchGroups(**{field: searchString}) for field in ['id', 'title']]), 'id') - - # Tack on some extra data, including whether each role is explicitly - # assigned ('explicit'), inherited ('inherited'), or not assigned at all (None). - results = [] - for group_info in explicit_groups: - groupId = group_info['id'] - group = acl.getGroupById(groupId) - group_info['title'] = group.getProperty('title', group_info['title']) - - explicitlyAssignedRoles = [] - for rolemaker_id, rolemaker in rolemakers: - # getRolesForPrincipal can return None - roles = rolemaker.getRolesForPrincipal(group) or () - explicitlyAssignedRoles.extend(roles) - - roleList = {} - for role in self.portal_roles: - canAssign = group.canAssignRole(role) - if role == 'Manager' and not self.is_zope_manager: - canAssign = False - roleList[role]={'canAssign': canAssign, - 'explicit': role in explicitlyAssignedRoles, - 'inherited': role in allInheritedRoles.get(groupId, [])} - - canDelete = group.canDelete() - if ('Manager' in explicitlyAssignedRoles or - 'Manager' in allInheritedRoles.get(groupId, [])): - if not self.is_zope_manager: - canDelete = False - - group_info['roles'] = roleList - group_info['can_delete'] = canDelete - results.append(group_info) - # Sort the groups by title - sortedResults = searchView.sort(results, 'title') - - # Reset the request variable, just in case. - self.request.set('__ignore_group_roles__', False) - return sortedResults - - def manageGroup(self, groups=None, delete=None): - if groups is None: - groups = [] - if delete is None: - delete = [] - CheckAuthenticator(self.request) - context = aq_inner(self.context) - - groupstool=context.portal_groups - utils = getToolByName(context, 'plone_utils') - groupstool = getToolByName(context, 'portal_groups') - - message = _(u'No changes made.') - - for group in groups: - roles=[r for r in self.request.form['group_' + group] if r] - group_obj = groupstool.getGroupById(group) - current_roles = group_obj.getRoles() - if not self.is_zope_manager: - # don't allow adding or removing the Manager role - if ('Manager' in roles) != ('Manager' in current_roles): - raise Forbidden - - groupstool.editGroup(group, roles=roles, groups=()) - message = _(u'Changes saved.') - - if delete: - for group_id in delete: - group = groupstool.getGroupById(group_id) - if 'Manager' in group.getRoles() and not self.is_zope_manager: - raise Forbidden - - groupstool.removeGroups(delete) - message=_(u'Group(s) deleted.') - - utils.addPortalMessage(message) - -class GroupMembershipControlPanel(UsersGroupsControlPanelView): - - def update(self): - self.groupname = getattr(self.request, 'groupname') - self.gtool = getToolByName(self, 'portal_groups') - self.mtool = getToolByName(self, 'portal_membership') - self.group = self.gtool.getGroupById(self.groupname) - self.grouptitle = self.group.getGroupTitleOrName() or self.groupname - - self.request.set('grouproles', self.group.getRoles() if self.group else []) - self.canAddUsers = True - if 'Manager' in self.request.get('grouproles') and not self.is_zope_manager: - self.canAddUsers = False - - self.groupquery = self.makeQuery(groupname=self.groupname) - self.groupkeyquery = self.makeQuery(key=self.groupname) - - form = self.request.form - submitted = form.get('form.submitted', False) - - self.searchResults = [] - self.searchString = '' - self.newSearch = False - - if submitted: - # add/delete before we search so we don't show stale results - toAdd = form.get('add', []) - if toAdd: - if not self.canAddUsers: - raise Forbidden - - for u in toAdd: - self.gtool.addPrincipalToGroup(u, self.groupname, self.request) - self.context.plone_utils.addPortalMessage(_(u'Changes made.')) - - toDelete = form.get('delete', []) - if toDelete: - for u in toDelete: - self.gtool.removePrincipalFromGroup(u, self.groupname, self.request) - self.context.plone_utils.addPortalMessage(_(u'Changes made.')) - - search = form.get('form.button.Search', None) is not None - edit = form.get('form.button.Edit', None) is not None and toDelete - add = form.get('form.button.Add', None) is not None and toAdd - findAll = form.get('form.button.FindAll', None) is not None and \ - not self.many_users - # The search string should be cleared when one of the - # non-search buttons has been clicked. - if findAll or edit or add: - form['searchstring'] = '' - self.searchString = form.get('searchstring', '') - if findAll or bool(self.searchString): - self.searchResults = self.getPotentialMembers(self.searchString) - - if search or findAll: - self.newSearch = True - - self.groupMembers = self.getMembers() - - def __call__(self): - self.update() - return self.index() - - def isGroup(self, itemName): - return self.gtool.isGroup(itemName) - - def getMembers(self): - searchResults = self.gtool.getGroupMembers(self.groupname) - - groupResults = [self.gtool.getGroupById(m) for m in searchResults] - groupResults.sort(key=lambda x: x is not None and normalizeString(x.getGroupTitleOrName())) - - userResults = [self.mtool.getMemberById(m) for m in searchResults] - userResults.sort(key=lambda x: x is not None and x.getProperty('fullname') is not None and normalizeString(x.getProperty('fullname')) or '') - - mergedResults = groupResults + userResults - return filter(None, mergedResults) - - def getPotentialMembers(self, searchString): - ignoredUsersGroups = [x.id for x in self.getMembers() + [self.group,] if x is not None] - return self.membershipSearch(searchString, ignore=ignoredUsersGroups) - -class UserMembershipControlPanel(UsersGroupsControlPanelView): - - def update(self): - self.userid = getattr(self.request, 'userid') - self.gtool = getToolByName(self, 'portal_groups') - self.mtool = getToolByName(self, 'portal_membership') - self.member = self.mtool.getMemberById(self.userid) - - form = self.request.form - - self.searchResults = [] - self.searchString = '' - self.newSearch = False - - if form.get('form.submitted', False): - delete = form.get('delete', []) - if delete: - for groupname in delete: - self.gtool.removePrincipalFromGroup(self.userid, groupname, self.request) - self.context.plone_utils.addPortalMessage(_(u'Changes made.')) - - add = form.get('add', []) - if add: - for groupname in add: - group = self.gtool.getGroupById(groupname) - if 'Manager' in group.getRoles() and not self.is_zope_manager: - raise Forbidden - - self.gtool.addPrincipalToGroup(self.userid, groupname, self.request) - self.context.plone_utils.addPortalMessage(_(u'Changes made.')) - - search = form.get('form.button.Search', None) is not None - findAll = form.get('form.button.FindAll', None) is not None and not self.many_groups - self.searchString = not findAll and form.get('searchstring', '') or '' - - if findAll or not self.many_groups or self.searchString != '': - self.searchResults = self.getPotentialGroups(self.searchString) - - if search or findAll: - self.newSearch = True - - self.groups = self.getGroups() - - def __call__(self): - self.update() - return self.index() - - def getGroups(self): - groupResults = [self.gtool.getGroupById(m) for m in self.gtool.getGroupsForPrincipal(self.member)] - groupResults.sort(key=lambda x: x is not None and normalizeString(x.getGroupTitleOrName())) - return filter(None, groupResults) - - def getPotentialGroups(self, searchString): - ignoredGroups = [x.id for x in self.getGroups() if x is not None] - return self.membershipSearch(searchString, searchUsers=False, ignore=ignoredGroups) diff --git a/plone/app/controlpanel/usergroups_groupdetails.pt b/plone/app/controlpanel/usergroups_groupdetails.pt deleted file mode 100644 index d6ce280..0000000 --- a/plone/app/controlpanel/usergroups_groupdetails.pt +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - -
- -
- - -
 
-
- -
- Portal status message -
- - -
- - -

Create a Group

-
- - -
- - - (Required) - -
- A unique identifier for the group. Can not be changed after creation. -
- - -
-
-
-
- -
- - -

- Edit Group Properties for unavailable -

- -
- Groups are logical collections of users, like departments and business units. - They are not directly related to permissions on a global level, you normally - use Roles for that - and let certain Groups have a particular role. -
- -
- - Up to Groups Overview - - -
- -
- Group Properties - -
- - -
- -
- - - - - - - - -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - -
- -
-
- - -
-
-
-
- - -
- -
- - - diff --git a/plone/app/controlpanel/usergroups_groupmembership.pt b/plone/app/controlpanel/usergroups_groupmembership.pt deleted file mode 100644 index 0c6bae6..0000000 --- a/plone/app/controlpanel/usergroups_groupmembership.pt +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - -
- -
- - -
-   -
-
- -
- Portal status message -
- -
- - -

Group Members

- -
- - Up to Groups Overview - - -

No group was specified.

- -

- Find a group here -

-
-
- - -

- Members of the Groupname group -

- -
- - Up to Groups Overview - - -

- You can add or remove groups and users from this particular group here. Note that this - doesn't actually delete the group or user, it is only removed from this group. -

- -
-

Current group members

- - - - - - - - - - - - - - - - - - - - - - - -
- - - User nameE-mail Address
- - - - - - () - - - - - Full Name - - () - - - - - - -
- - -

There is no group or user attached to this group.

- - - - - -

Search for new group members

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Quick search: - - - - -
- - Group/User nameE-mail Address
- - - - - - Full Name - - () - - - - - - - - () - - - - - - -
No matches - Enter a group or user name to search for. - - Enter a group or user name to search for or click 'Show All'. -
- - - - - -
- - - - - - - - - - -
- - -
-
- -
- - - diff --git a/plone/app/controlpanel/usergroups_groupsoverview.pt b/plone/app/controlpanel/usergroups_groupsoverview.pt deleted file mode 100644 index 8ce1210..0000000 --- a/plone/app/controlpanel/usergroups_groupsoverview.pt +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - -
- -
- -
 
-
- -
- Portal status message -
- -
- - Site Setup - -

Groups Overview

- -
- -

- - Groups are logical collections of users, such as - departments and business units. Groups are not directly - related to permissions on a global level, you normally - use Roles for that - and let certain Groups have a - particular role. - - - The symbol - - indicates a role inherited from membership in another group. - -

- -

- Note: Some or all of your PAS groups - source plugins do not allow listing of groups, so you - may not see the groups defined by those plugins unless - doing a specific search. -

- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - Group Search - - - - - - - - -
- Group Name - - Roles - - Remove Group -
- Role -
- - - -   - () - - - - - - - - - -
- No matches -
- - - -
- - - - - - - - - -
-
-
- -
- - - diff --git a/plone/app/controlpanel/usergroups_usermembership.pt b/plone/app/controlpanel/usergroups_usermembership.pt deleted file mode 100644 index 622140e..0000000 --- a/plone/app/controlpanel/usergroups_usermembership.pt +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - -
- - - -
- Portal status message -
- - -
- -
- - - diff --git a/plone/app/controlpanel/usergroups_usersoverview.pt b/plone/app/controlpanel/usergroups_usersoverview.pt deleted file mode 100644 index be82771..0000000 --- a/plone/app/controlpanel/usergroups_usersoverview.pt +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - -
-
- -
 
-
- -
- Portal status message -
- -
- - -

Users Overview

- -
-

- Click the user's name to see and change the details of a - specific user. You can also add and remove users. -

-

- Note that roles set here apply directly to a user. - The symbol - indicates a role inherited from membership in a group. -

-

- Note - Some or all of your PAS user source - plugins do not allow listing of users, so you may not see - the users defined by those plugins unless doing a specific - search. -

-

- - - -

-
- - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
User nameRolesReset PasswordRemove user
Role
- - Full Name - login name - - - - - - - - - - - - - -
No matches - Enter a username to search for - - Enter a username to search for, or click 'Show All' -
- -
- - - - - - - -
- -
- - - - -
-
-
- -
- - - - diff --git a/plone/app/controlpanel/usergroupssettings.pt b/plone/app/controlpanel/usergroupssettings.pt deleted file mode 100644 index 3fb055c..0000000 --- a/plone/app/controlpanel/usergroupssettings.pt +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - -
- -
- -
 
-
- -
- Portal status message -
- -
- - -

User/Groups Settings

- -
- -
-
-
-
- -