/* * A CCNx command line utility. * * Copyright (C) 2008-2012 Palo Alto Research Center, Inc. * * This work is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. * This work 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ package org.ccnx.ccn.utils.explorer; import java.awt.Color; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.border.BevelBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.ccnx.ccn.config.SystemConfiguration; import org.ccnx.ccn.config.UserConfiguration; import org.ccnx.ccn.io.content.Link; import org.ccnx.ccn.profiles.security.access.AccessDeniedException; import org.ccnx.ccn.profiles.security.access.group.Group; import org.ccnx.ccn.profiles.security.access.group.GroupAccessControlManager; import org.ccnx.ccn.profiles.security.access.group.GroupManager; import org.ccnx.ccn.protocol.Component; import org.ccnx.ccn.protocol.ContentName; public class GroupManagerGUI extends JDialog implements ActionListener, ListSelectionListener { private static final long serialVersionUID = 1L; private GroupManager gm; private PrincipalEnumerator pEnum; ContentName userStorage = new ContentName(UserConfiguration.defaultNamespace(), "Users"); ContentName groupStorage = new ContentName(UserConfiguration.defaultNamespace(), "Groups"); private ArrayList<ContentName> usersContentNameList = new ArrayList<ContentName>(); private ArrayList<ContentName> groupsContentNameList = new ArrayList<ContentName>(); private ArrayList<ContentName> groupMembersContentNameList = new ArrayList<ContentName>(); private SortedListModel groupEditorModel = null; private SortedListModel groupMembershipListModel = null; private SortedListModel userSelectorModel = null; private SortedListModel groupSelectorModel = null; // group updates private String selectedGroupFriendlyName; private ArrayList<Link> membersToAdd; private ArrayList<Link> membersToRemove; // GUI elements private JPanel membershipPanel; private JLabel newGroupLabel; private JList groupEditor; private JList userSelector; private JList groupSelector; private JList groupMembershipList; private JTextField newGroupName; private JButton createGroupButton; private JButton addMemberButton; private JButton removeMemberButton; private JButton applyChangesButton; private JButton cancelChangesButton; private JScrollPane scrollPaneGroupMembership; private JScrollPane scrollPaneUsers; private JScrollPane scrollPaneGroups; // GUI positions private int LEFT_MARGIN = 30; private int GROUP_EDITOR_HEIGHT = 100; private int VERTICAL_OFFSET = GROUP_EDITOR_HEIGHT + 110; private int SELECTOR_WIDTH = 200; private int SELECTOR_HEIGHT = 300; public GroupManagerGUI(String path, GroupAccessControlManager acm) { super(); setTitle("Group Manager"); getContentPane().setLayout(null); setBounds(100, 100, (SELECTOR_WIDTH * 2) + 180, VERTICAL_OFFSET + SELECTOR_HEIGHT + 180); // enumerate existing users and groups try{ gm = acm.groupManager(); } catch (Exception e) { e.printStackTrace(); } pEnum = new PrincipalEnumerator(gm); usersContentNameList = pEnum.enumerateUsers(); groupsContentNameList = pEnum.enumerateGroups(); groupMembershipListModel = new SortedListModel(); // group list (single group selection) final JLabel groupEditorLabel = new JLabel(); groupEditorLabel.setText("Select an existing group:"); groupEditorLabel.setBounds(LEFT_MARGIN, 10, 200, 15); getContentPane().add(groupEditorLabel); final JScrollPane scrollPaneGroupEditor = new JScrollPane(); scrollPaneGroupEditor.setBounds(LEFT_MARGIN, 37, 388, GROUP_EDITOR_HEIGHT); getContentPane().add(scrollPaneGroupEditor); groupEditorModel = new SortedListModel(); groupEditorModel.addAll(groupsContentNameList.toArray()); groupEditor = new JList(groupEditorModel); groupEditor.setName("groups"); scrollPaneGroupEditor.setViewportView(groupEditor); groupEditor.setBorder(new BevelBorder(BevelBorder.LOWERED)); groupEditor.addListSelectionListener(this); // create new group newGroupLabel = new JLabel(); newGroupLabel.setText("New group name: "); newGroupLabel.setBounds(LEFT_MARGIN, GROUP_EDITOR_HEIGHT + 60, 150, 20); getContentPane().add(newGroupLabel); newGroupName = new JTextField(); newGroupName.setBounds(LEFT_MARGIN + 150, GROUP_EDITOR_HEIGHT + 60, 150, 20); getContentPane().add(newGroupName); createGroupButton = new JButton(); createGroupButton.setText("Create New Group"); createGroupButton.addActionListener(this); createGroupButton.setBounds(LEFT_MARGIN, GROUP_EDITOR_HEIGHT + 60, 200, 20); getContentPane().add(createGroupButton); // Membership panel membershipPanel = new JPanel(); membershipPanel.setLayout(null); membershipPanel.setBounds(LEFT_MARGIN, VERTICAL_OFFSET, (SELECTOR_WIDTH * 2) + 110, SELECTOR_HEIGHT + 140); getContentPane().add(membershipPanel); // user selector userSelectorModel = new SortedListModel(); userSelectorModel.addAll(usersContentNameList.toArray()); userSelector = new JList(userSelectorModel); userSelector.setName("users"); userSelector.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // userSelector.setBorder(new BevelBorder(BevelBorder.LOWERED)); scrollPaneUsers = new JScrollPane(); scrollPaneUsers.setViewportView(userSelector); scrollPaneUsers.setBounds(10, 30, SELECTOR_WIDTH, SELECTOR_HEIGHT / 2); scrollPaneUsers.setBorder(BorderFactory.createTitledBorder("Users")); membershipPanel.add(scrollPaneUsers); // group selector groupSelectorModel = new SortedListModel(); groupSelectorModel.addAll(groupsContentNameList.toArray()); groupSelector = new JList(groupSelectorModel); groupSelector.setName("group_selector"); groupSelector.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // groupSelector.setBorder(new BevelBorder(BevelBorder.LOWERED)); scrollPaneGroups = new JScrollPane(); scrollPaneGroups.setViewportView(groupSelector); scrollPaneGroups.setBounds(10, 40 + (SELECTOR_HEIGHT/2), SELECTOR_WIDTH, SELECTOR_HEIGHT / 2); scrollPaneGroups.setBorder(BorderFactory.createTitledBorder("Groups")); membershipPanel.add(scrollPaneGroups); // add and remove buttons addMemberButton = new JButton(); addMemberButton.addActionListener(this); addMemberButton.setText("->"); addMemberButton.setBounds(SELECTOR_WIDTH + 20, 80, 52, 25); membershipPanel.add(addMemberButton); removeMemberButton = new JButton(); removeMemberButton.addActionListener(this); removeMemberButton.setText("<-"); removeMemberButton.setBounds(SELECTOR_WIDTH + 20, 150, 52, 25); membershipPanel.add(removeMemberButton); // group membership list groupMembershipList = new JList(groupMembershipListModel); groupMembershipList.setName("groupMembers"); groupMembershipList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // groupMembershipList.setBorder(new BevelBorder(BevelBorder.LOWERED)); scrollPaneGroupMembership = new JScrollPane(); scrollPaneGroupMembership.setViewportView(groupMembershipList); scrollPaneGroupMembership.setBounds(SELECTOR_WIDTH + 90, 30, SELECTOR_WIDTH, SELECTOR_HEIGHT + 10); scrollPaneGroupMembership.setBorder(BorderFactory.createTitledBorder("Group Members")); membershipPanel.add(scrollPaneGroupMembership); // apply and cancel buttons applyChangesButton = new JButton(); applyChangesButton.addActionListener(this); applyChangesButton.setMargin(new Insets(2, 2, 2, 2)); applyChangesButton.setBounds(LEFT_MARGIN, SELECTOR_HEIGHT + 90, 112, 25); applyChangesButton.setText("Apply Changes"); membershipPanel.add(applyChangesButton); cancelChangesButton = new JButton(); cancelChangesButton.addActionListener(this); cancelChangesButton.setMargin(new Insets(2, 2, 2, 2)); cancelChangesButton.setText("Cancel Changes"); cancelChangesButton.setBounds(320, SELECTOR_HEIGHT + 90, 112, 25); membershipPanel.add(cancelChangesButton); selectGroupView(); } /** * Display the basic view in which the user can select a group to edit. */ public void selectGroupView() { createGroupButton.setVisible(true); newGroupLabel.setVisible(false); newGroupName.setVisible(false); membershipPanel.setVisible(false); } /** * Display the view which allows a user to edit the membership of a group. */ public void editGroupMembershipView() { userSelector.clearSelection(); groupSelector.clearSelection(); groupMembershipList.clearSelection(); createGroupButton.setVisible(true); newGroupLabel.setVisible(false); newGroupName.setVisible(false); applyChangesButton.setText("Apply Changes"); cancelChangesButton.setText("Cancel Changes"); membershipPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK, 2), "Group: " + selectedGroupFriendlyName)); membershipPanel.setVisible(true); } /** * Display the view which allows the user to create a new group. */ public void createNewGroupView() { userSelector.clearSelection(); groupSelector.clearSelection(); groupMembershipList.clearSelection(); createGroupButton.setVisible(false); newGroupLabel.setVisible(true); newGroupName.setVisible(true); applyChangesButton.setText("Create Group"); cancelChangesButton.setText("Cancel"); membershipPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK, 2), "New Group")); membershipPanel.setVisible(true); } public void actionPerformed(ActionEvent e) { if (applyChangesButton == e.getSource()) applyChanges(); else if (cancelChangesButton == e.getSource()) cancelChanges(); else if (addMemberButton == e.getSource()) addPrincipals(); else if (removeMemberButton == e.getSource()) removePrincipals(); else if (createGroupButton == e.getSource()) createNewGroup(); } /** * Apply all batched operations (addition or removal of principals) */ private void applyChanges() { if (selectedGroupFriendlyName != null) { // we are applying changes to an existing group try { System.out.println("Members to add:"); for (Link l: membersToAdd) { System.out.println(l.targetName()); } System.out.println("Members to remove:"); for (Link l: membersToRemove) { System.out.println(l.targetName()); } Group g = gm.getGroup(selectedGroupFriendlyName, SystemConfiguration.getDefaultTimeout()); g.modify(membersToAdd, membersToRemove); } catch (AccessDeniedException ade) { JOptionPane.showMessageDialog(this, "You do not have the access right to edit this group."); ade.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } else { // we are creating a new group String newName = newGroupName.getText(); if (validateNewGroupName(newName)) { try { System.out.println("Members to add:"); for (Link l: membersToAdd) { System.out.println(l.targetName()); } gm.createGroup(newName, membersToAdd, SystemConfiguration.getDefaultTimeout()); } catch (Exception e) { e.printStackTrace(); } groupsContentNameList = pEnum.enumerateGroups(); groupEditorModel.clear(); groupEditorModel.addAll(groupsContentNameList.toArray()); selectGroupView(); } } } /** * Cancel all batched operations (addition or removal of principals) */ private void cancelChanges() { membersToAdd = new ArrayList<Link>(); membersToRemove = new ArrayList<Link>(); populateGroupMembershipList(); populatePrincipalsList(); if (selectedGroupFriendlyName == null) selectGroupView(); } /** * Add selected principals (users of groups) to the group * identified by selectedGroupFriendlyName. * Note that addition (and removal) operations are batched and only applied when the * method applyChanges() is called. */ private void addPrincipals() { // add selected users ArrayList<Object> usersToAdd = new ArrayList<Object>(); int[] selectedUsers = userSelector.getSelectedIndices(); for (int index: selectedUsers) { Object obj = userSelector.getModel().getElementAt(index); usersToAdd.add(obj); } for (Object obj: usersToAdd) { ((SortedListModel) groupMembershipList.getModel()).add(obj); ((SortedListModel) userSelector.getModel()).removeElement(obj); ContentName userContentName = (ContentName) obj; Link lk = new Link(userContentName); if (membersToRemove.contains(lk)) membersToRemove.remove(lk); else membersToAdd.add(lk); } userSelector.clearSelection(); // add selected groups ArrayList<Object> groupsToAdd = new ArrayList<Object>(); int[] selectedGroups = groupSelector.getSelectedIndices(); for (int index: selectedGroups) { Object obj = groupSelector.getModel().getElementAt(index); groupsToAdd.add(obj); } for (Object obj: groupsToAdd) { ((SortedListModel) groupMembershipList.getModel()).add(obj); ((SortedListModel) groupSelector.getModel()).removeElement(obj); ContentName groupContentName = (ContentName) obj; Link lk = new Link(groupContentName); if (membersToRemove.contains(lk)) membersToRemove.remove(lk); else membersToAdd.add(lk); } groupSelector.clearSelection(); } /** * Remove selected principals (users of groups) from the group * identified by selectedGroupFriendlyName. * Note that removal (and addition) operations are batched and only applied when the * method applyChanges() is called. */ private void removePrincipals() { ArrayList<Object> principalsToRemove = new ArrayList<Object>(); int[] selectedPrincipals = groupMembershipList.getSelectedIndices(); for (int index: selectedPrincipals) { Object obj = groupMembershipList.getModel().getElementAt(index); principalsToRemove.add(obj); } for (Object obj: principalsToRemove) { ContentName principalContentName = (ContentName) obj; if (usersContentNameList.contains(principalContentName)) ((SortedListModel) userSelector.getModel()).add(obj); else if (groupsContentNameList.contains(principalContentName)) ((SortedListModel) groupSelector.getModel()).add(obj); else System.out.println("Warning: the principal " + principalContentName + " is neither a known group or a know user."); ((SortedListModel) groupMembershipList.getModel()).removeElement(obj); Link lk = new Link(principalContentName); if (membersToAdd.contains(lk)) membersToAdd.remove(lk); else membersToRemove.add(lk); } groupMembershipList.clearSelection(); } /** * Create a new group */ private void createNewGroup() { groupEditor.clearSelection(); newGroupName.setText(""); selectedGroupFriendlyName = null; populateGroupMembershipList(); populatePrincipalsList(); membersToAdd = new ArrayList<Link>(); membersToRemove = new ArrayList<Link>(); createNewGroupView(); } /** * Display the members of selectedGroupFriendlyName. * If selectedGroupFriendlyName is null, the membership list is empty (e.g. we are creating a new group) */ public void populateGroupMembershipList() { groupMembershipListModel.clear(); groupMembersContentNameList = pEnum.enumerateGroupMembers(selectedGroupFriendlyName); groupMembershipListModel.addAll(groupMembersContentNameList.toArray()); } /** * Display the list of principals (users and groups) which are not already included * in the membership list of selectedGroupFriendlyName. */ public void populatePrincipalsList() { userSelectorModel.clear(); ArrayList<ContentName> usersNotInGroup = new ArrayList<ContentName>(); usersNotInGroup.addAll(usersContentNameList); usersNotInGroup.removeAll(groupMembersContentNameList); userSelectorModel.addAll(usersNotInGroup.toArray()); groupSelectorModel.clear(); ArrayList<ContentName> groupsNotInGroup = new ArrayList<ContentName>(); groupsNotInGroup.addAll(groupsContentNameList); groupsNotInGroup.removeAll(groupMembersContentNameList); groupSelectorModel.addAll(groupsNotInGroup.toArray()); } /** * Display the membership list and the list of principals that can be added * to the selected group. */ public void valueChanged(ListSelectionEvent e) { JList list = (JList) e.getSource(); if(list.getSelectedValue() != null){ ContentName groupContentName = (ContentName) list.getSelectedValue(); selectedGroupFriendlyName = Component.printNative(groupContentName.lastComponent()); membersToAdd = new ArrayList<Link>(); membersToRemove = new ArrayList<Link>(); populateGroupMembershipList(); populatePrincipalsList(); editGroupMembershipView(); } } /** * Checks the correctness of the name selected for a new group * @param name the name to validate * @return true if the name is valid, false otherwise. */ private boolean validateNewGroupName(String name) { if (name.equals("")) { JOptionPane.showMessageDialog(this, "The new group needs a name."); return false; } return true; } }