/* * RHQ Management Platform * Copyright (C) 2005-2012 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.coregui.client.admin.roles; import java.util.ArrayList; import java.util.List; import java.util.Set; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.Record; import com.smartgwt.client.types.Overflow; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.Label; import com.smartgwt.client.widgets.form.fields.FormItem; import com.smartgwt.client.widgets.form.fields.TextItem; import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.tab.Tab; import com.smartgwt.client.widgets.tab.TabSet; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.resource.group.GroupCategory; import org.rhq.coregui.client.BookmarkableView; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.ImageManager; import org.rhq.coregui.client.PermissionsLoadedListener; import org.rhq.coregui.client.PermissionsLoader; import org.rhq.coregui.client.UserSessionManager; import org.rhq.coregui.client.ViewPath; import org.rhq.coregui.client.admin.users.UsersDataSource; import org.rhq.coregui.client.bundle.group.BundleGroupSelector; import org.rhq.coregui.client.components.form.AbstractRecordEditor; import org.rhq.coregui.client.components.form.EnhancedDynamicForm; import org.rhq.coregui.client.components.selector.AssignedItemsChangedEvent; import org.rhq.coregui.client.components.selector.AssignedItemsChangedHandler; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.inventory.resource.selection.ResourceGroupSelector; import org.rhq.coregui.client.util.enhanced.EnhancedVLayout; /** * A form for viewing and/or editing an RHQ {@link Role role}. * * @author Ian Springer */ public class RoleEditView extends AbstractRecordEditor<RolesDataSource> implements BookmarkableView { private static final String HEADER_ICON = "global/Role_24.png"; private Tab permissionsTab; private PermissionsEditor permissionsEditor; private Tab resourceGroupsTab; private ResourceGroupSelector resourceGroupSelector; private Tab subjectsTab; private RoleSubjectSelector subjectSelector; private Tab ldapGroupsTab; private RoleLdapGroupSelector ldapGroupSelector; private Tab bundleGroupsTab; private BundleGroupSelector bundleGroupSelector; private boolean hasManageSecurityPermission; private boolean isLdapConfigured; private boolean isSystemRole; public RoleEditView(int roleId) { super(new RolesDataSource(), roleId, MSG.common_label_role(), HEADER_ICON); } @Override public void renderView(ViewPath viewPath) { super.renderView(viewPath); this.isSystemRole = RolesDataSource.isSystemRoleId(getRecordId()); // Step 1 of async init: load current user's global permissions. new PermissionsLoader().loadExplicitGlobalPermissions(new PermissionsLoadedListener() { public void onPermissionsLoaded(Set<Permission> perms) { if (perms == null) { // TODO: i18n CoreGUI.getErrorHandler().handleError( "Failed to load global permissions for current user. Perhaps the Server is down."); return; } RoleEditView.this.hasManageSecurityPermission = perms.contains(Permission.MANAGE_SECURITY); // Step 2 of async init: check if LDAP is configured. checkIfLdapConfigured(); } }); } @Override protected boolean isFormReadOnly() { return (isReadOnly() || this.isSystemRole); } private void checkIfLdapConfigured() { GWTServiceLookup.getLdapService().checkLdapConfiguredStatus(new AsyncCallback<Boolean>() { public void onSuccess(Boolean isLdapConfigured) { RoleEditView.this.isLdapConfigured = isLdapConfigured; // Step 3 of async init: call super.init(). init(); } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); return; } }); } private void init() { final boolean isReadOnly = (!this.hasManageSecurityPermission); init(isReadOnly); } @Override protected EnhancedVLayout buildContentPane() { EnhancedVLayout contentPane = new EnhancedVLayout(); contentPane.setWidth100(); contentPane.setHeight100(); contentPane.setOverflow(Overflow.AUTO); EnhancedDynamicForm form = buildForm(); setForm(form); EnhancedVLayout topPane = new EnhancedVLayout(); topPane.setWidth100(); topPane.setHeight(80); topPane.addMember(form); contentPane.addMember(topPane); TabSet tabSet = new TabSet(); tabSet.setWidth100(); tabSet.setHeight100(); // TODO: Also add these tabs if the session subject is a member of the Role being viewed. if (this.hasManageSecurityPermission) { this.permissionsTab = buildPermissionsTab(tabSet); tabSet.addTab(permissionsTab); if (!this.isSystemRole) { this.resourceGroupsTab = buildResourceGroupsTab(tabSet); tabSet.addTab(resourceGroupsTab); this.bundleGroupsTab = buildBundleGroupsTab(tabSet); tabSet.addTab(bundleGroupsTab); } this.subjectsTab = buildSubjectsTab(tabSet); tabSet.addTab(subjectsTab); this.ldapGroupsTab = buildLdapGroupsTab(tabSet); tabSet.addTab(ldapGroupsTab); } contentPane.addMember(tabSet); return contentPane; } private Tab buildPermissionsTab(TabSet tabSet) { Tab tab = new Tab(MSG.common_title_permissions(), "global/Locked_16.png"); // NOTE: We will set the tab content to the permissions editor later once the Role has been fetched. return tab; } private Tab buildResourceGroupsTab(TabSet tabSet) { Tab tab = new Tab(MSG.common_title_resourceGroups(), ImageManager.getGroupIcon(GroupCategory.MIXED)); // NOTE: We will set the tab content to the resource group selector later once the Role has been fetched. return tab; } private Tab buildBundleGroupsTab(TabSet tabSet) { Tab tab = new Tab(MSG.common_title_bundleGroups(), ImageManager.getBundleGroupIcon()); // NOTE: We will set the tab content to the bundle group selector later once the Role has been fetched. return tab; } private Tab buildSubjectsTab(TabSet tabSet) { Tab tab = new Tab(MSG.common_title_users(), "global/User_16.png"); // NOTE: We will set the tab content to the subject selector later once the Role has been fetched. return tab; } private Tab buildLdapGroupsTab(TabSet tabSet) { Tab tab = new Tab(MSG.common_title_ldapGroups(), "global/Role_16.png"); // NOTE: We will set the tab content to the LDAP group selector later once the Role has been fetched. return tab; } @Override protected Record createNewRecord() { Role role = new Role(); role.addPermission(Permission.VIEW_USERS); Record roleRecord = RolesDataSource.getInstance().copyValues(role); return roleRecord; } protected void editRecord(Record record) { super.editRecord(record); // A user can always view their own assigned roles, but only users with MANAGE_SECURITY can view or update // other users' assigned roles. Subject sessionSubject = UserSessionManager.getSessionSubject(); int sessionSubjectId = sessionSubject.getId(); Record[] subjectRecords = record.getAttributeAsRecordArray(RolesDataSource.Field.SUBJECTS); boolean isMemberOfRole = false; for (Record subjectRecord : subjectRecords) { int subjectId = subjectRecord.getAttributeAsInt(RolesDataSource.Field.ID); if (subjectId == sessionSubjectId) { isMemberOfRole = true; } } if (this.hasManageSecurityPermission || isMemberOfRole) { // Create the permission editor and selectors and add them to the corresponding tabs. this.permissionsEditor = new PermissionsEditor(this, !hasManageSecurityPermission || this.isSystemRole); updateTab(this.permissionsTab, this.permissionsEditor); if (!this.isSystemRole) { Record[] groupRecords = record.getAttributeAsRecordArray(RolesDataSource.Field.RESOURCE_GROUPS); ListGridRecord[] groupListGridRecords = toListGridRecordArray(groupRecords); this.resourceGroupSelector = new RoleResourceGroupSelector(groupListGridRecords, !this.hasManageSecurityPermission); this.resourceGroupSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() { public void onSelectionChanged(AssignedItemsChangedEvent event) { onItemChanged(); } }); updateTab(this.resourceGroupsTab, this.resourceGroupSelector); Record[] bundleGroupRecords = record.getAttributeAsRecordArray(RolesDataSource.Field.BUNDLE_GROUPS); ListGridRecord[] bundleGroupListGridRecords = toListGridRecordArray(bundleGroupRecords); this.bundleGroupSelector = new RoleBundleGroupSelector(bundleGroupListGridRecords, !this.hasManageSecurityPermission); this.bundleGroupSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() { public void onSelectionChanged(AssignedItemsChangedEvent event) { onItemChanged(); } }); updateTab(this.bundleGroupsTab, this.bundleGroupSelector); } ListGridRecord[] subjectListGridRecords = toListGridRecordArray(subjectRecords); if (getRecordId() == RolesDataSource.ID_SUPERUSER) { // If this is the superuser role, make sure the rhqadmin record is disabled, so it cannot be removed // from the role, and filter the overlord record out, so users don't even know it exists. List<ListGridRecord> filteredSubjectRecords = new ArrayList<ListGridRecord>(); for (ListGridRecord subjectListGridRecord : subjectListGridRecords) { int subjectId = subjectListGridRecord.getAttributeAsInt(UsersDataSource.Field.ID); if (subjectId == UsersDataSource.ID_RHQADMIN) { subjectListGridRecord.setEnabled(false); } if (subjectId != UsersDataSource.ID_OVERLORD) { filteredSubjectRecords.add(subjectListGridRecord); } } subjectListGridRecords = filteredSubjectRecords.toArray(new ListGridRecord[filteredSubjectRecords .size()]); } this.subjectSelector = new RoleSubjectSelector(subjectListGridRecords, !this.hasManageSecurityPermission); this.subjectSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() { public void onSelectionChanged(AssignedItemsChangedEvent event) { onItemChanged(); } }); updateTab(this.subjectsTab, this.subjectSelector); if (this.isLdapConfigured) { Record[] ldapGroupRecords = record.getAttributeAsRecordArray(RolesDataSource.Field.LDAP_GROUPS); ListGridRecord[] ldapGroupListGridRecords = toListGridRecordArray(ldapGroupRecords); this.ldapGroupSelector = new RoleLdapGroupSelector(ldapGroupListGridRecords, !this.hasManageSecurityPermission); this.ldapGroupSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() { public void onSelectionChanged(AssignedItemsChangedEvent event) { onItemChanged(); } }); updateTab(this.ldapGroupsTab, this.ldapGroupSelector); } else { // LDAP is not configured for this RHQ Server - display a message on the LDAP Groups tab informing the // user of this along with a link to the System Settings view. Label label = new Label("<b>" + MSG.common_msg_emphasizedNotePrefix() + "</b> " + MSG.view_adminRoles_noLdap("href='#Administration/Configuration/SystemSettings'", MSG.view_adminConfig_systemSettings())); label.setWidth100(); label.setHeight(20); label.setPadding(10); updateTab(this.ldapGroupsTab, label); } } this.permissionsEditor.redraw(); } @Override protected List<FormItem> createFormItems(EnhancedDynamicForm form) { List<FormItem> items = new ArrayList<FormItem>(); TextItem nameItem = new TextItem(RolesDataSource.Field.NAME); nameItem.setShowTitle(true); nameItem.setSelectOnFocus(true); nameItem.setTabIndex(1); nameItem.setAttribute(EnhancedDynamicForm.OUTPUT_AS_HTML_ATTRIBUTE, true); items.add(nameItem); TextItem descriptionItem = new TextItem(RolesDataSource.Field.DESCRIPTION); descriptionItem.setShowTitle(true); descriptionItem.setTabIndex(5); descriptionItem.setColSpan(form.getNumCols()); descriptionItem.setAttribute(EnhancedDynamicForm.OUTPUT_AS_HTML_ATTRIBUTE, true); items.add(descriptionItem); return items; } @Override protected void save(DSRequest requestProperties) { // Grab the currently assigned sets from each of the selectors and stick them into the corresponding canvas // items on the form, so when the form is saved, they'll get submitted along with the rest of the simple fields // to the datasource's add or update methods. if (this.resourceGroupSelector != null) { ListGridRecord[] resourceGroupRecords = this.resourceGroupSelector.getSelectedRecords(); getForm().setValue(RolesDataSource.Field.RESOURCE_GROUPS, resourceGroupRecords); } if (this.subjectSelector != null) { ListGridRecord[] subjectRecords = this.subjectSelector.getSelectedRecords(); getForm().setValue(RolesDataSource.Field.SUBJECTS, subjectRecords); } if (this.ldapGroupSelector != null) { ListGridRecord[] ldapGroupRecords = this.ldapGroupSelector.getSelectedRecords(); getForm().setValue(RolesDataSource.Field.LDAP_GROUPS, ldapGroupRecords); } if (this.bundleGroupSelector != null) { ListGridRecord[] bundleGroupRecords = this.bundleGroupSelector.getSelectedRecords(); getForm().setValue(RolesDataSource.Field.BUNDLE_GROUPS, bundleGroupRecords); } // Submit the form values to the datasource. super.save(requestProperties); } @Override protected void reset() { super.reset(); if (this.permissionsEditor != null) { this.permissionsEditor.reset(); } if (this.resourceGroupSelector != null) { this.resourceGroupSelector.reset(); } if (this.subjectSelector != null) { this.subjectSelector.reset(); } if (this.ldapGroupSelector != null) { this.ldapGroupSelector.reset(); } if (this.bundleGroupSelector != null) { this.bundleGroupSelector.reset(); } } private static void updateTab(Tab tab, Canvas content) { if (tab == null) { throw new IllegalStateException("A null tab was specified."); } tab.getTabSet().updateTab(tab, content); } }