Finalize listener mechanism
authorBruno Sinou <bsinou@argeo.org>
Thu, 17 Sep 2015 15:31:40 +0000 (15:31 +0000)
committerBruno Sinou <bsinou@argeo.org>
Thu, 17 Sep 2015 15:31:40 +0000 (15:31 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8417 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminImages.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserTableViewer.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/commands/NewUser.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserEditor.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java

index e7cd5df464190440032759528eabf264fffedff1..3027c364aa062c817b6386de8063e5b679141e2f 100644 (file)
  */
 package org.argeo.security.ui.admin;
 
+import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.swt.graphics.Image;
 
 /** Shared icons that must be declared programmatically . */
 public class SecurityAdminImages {
        private final static String PREFIX = "icons/";
 
-       public final static Image ICON_USER = SecurityAdminPlugin
-                       .getImageDescriptor(PREFIX + "user.gif").createImage();
+       public final static ImageDescriptor ICON_REMOVE_DESC = SecurityAdminPlugin
+                       .getImageDescriptor(PREFIX + "remove.gif");
+       public final static ImageDescriptor ICON_USER_DESC = SecurityAdminPlugin
+                       .getImageDescriptor(PREFIX + "user.gif");
+       
+       public final static Image ICON_USER = ICON_USER_DESC.createImage();
        public final static Image ICON_GROUP = SecurityAdminPlugin
                        .getImageDescriptor(PREFIX + "users.gif").createImage();
 
index 637b8e6e4e3804fae2fd1093bb80d4275166e2f8..ed29315e44c42532645f8d061167ff31bbde5345 100644 (file)
@@ -143,11 +143,6 @@ public class UserTableViewer extends Composite {
                refreshFilteredList(filter);
        }
 
-       // /** Returns filter String or null if no filter Text widget */
-       // private String getFilterString() {
-       // return hasFilter ? filterTxt.getText() : null;
-       // }
-
        /**
         * Build repository request : caller might overwrite in order to display a
         * subset of all users
@@ -158,8 +153,6 @@ public class UserTableViewer extends Composite {
                        Role[] roles = userAdmin.getRoles(filter);
                        // Display all users and groups
                        for (Role role : roles)
-                               // if (role.getType() == Role.USER && role.getType() !=
-                               // Role.GROUP)
                                users.add((User) role);
                } catch (InvalidSyntaxException e) {
                        throw new ArgeoException("Unable to get roles with filter: "
index a0b8da2fa22c6e7c78ad7e109f3703f73b8176de..d8d697a1f17aa08a8ab4498ef7cb0b159d815d43 100644 (file)
@@ -107,7 +107,6 @@ public class NewUser extends AbstractHandler {
                        String username = mainUserInfo.getUsername();
                        try {
                                userAdminWrapper.beginTransactionIfNeeded();
-                               char[] password = mainUserInfo.getPassword();
                                User user = (User) userAdminWrapper.getUserAdmin().createRole(
                                                getDn(username), Role.USER);
 
@@ -130,6 +129,7 @@ public class NewUser extends AbstractHandler {
                                if (UiAdminUtils.notNull(mailStr))
                                        props.put(UserAdminConstants.KEY_MAIL, mailStr);
 
+                               char[] password = mainUserInfo.getPassword();
                                user.getCredentials().put(null, password);
 
                                userAdminWrapper.notifyListeners(new UserAdminEvent(null,
index c7cecf21015e17806546af296569ed75172388fe..f3fdabfb19ccf16650e664280ef4963686aca5b7 100644 (file)
 package org.argeo.security.ui.admin.internal.parts;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.jcr.ArgeoNames;
+import org.argeo.security.ui.admin.SecurityAdminImages;
 import org.argeo.security.ui.admin.internal.ColumnDefinition;
+import org.argeo.security.ui.admin.internal.UiAdminUtils;
 import org.argeo.security.ui.admin.internal.UserAdminConstants;
 import org.argeo.security.ui.admin.internal.UserAdminWrapper;
 import org.argeo.security.ui.admin.internal.UserTableViewer;
+import org.argeo.security.ui.admin.internal.parts.UserEditor.GroupChangeListener;
+import org.argeo.security.ui.admin.internal.parts.UserEditor.MainInfoListener;
 import org.argeo.security.ui.admin.internal.providers.CommonNameLP;
 import org.argeo.security.ui.admin.internal.providers.MailLP;
 import org.argeo.security.ui.admin.internal.providers.RoleIconLP;
 import org.argeo.security.ui.admin.internal.providers.UserNameLP;
 import org.argeo.security.ui.admin.internal.providers.UserTableDefaultDClickListener;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ToolBarManager;
 import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.DND;
@@ -42,12 +48,16 @@ import org.eclipse.swt.dnd.DropTargetEvent;
 import org.eclipse.swt.dnd.TextTransfer;
 import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Cursor;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.ui.forms.AbstractFormPart;
 import org.eclipse.ui.forms.IManagedForm;
 import org.eclipse.ui.forms.SectionPart;
@@ -79,111 +89,115 @@ public class GroupMainPage extends FormPage implements ArgeoNames {
        }
 
        protected void createFormContent(final IManagedForm mf) {
-               try {
-                       ScrolledForm form = mf.getForm();
-                       refreshFormTitle();
-
-                       // Body
-                       Composite body = form.getBody();
-                       GridLayout mainLayout = new GridLayout();
-                       body.setLayout(mainLayout);
-                       appendOverviewPart(body);
-                       appendMembersPart(body);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot create form content", e);
-               }
+               ScrolledForm form = mf.getForm();
+               Composite body = form.getBody();
+               GridLayout mainLayout = new GridLayout();
+               body.setLayout(mainLayout);
+               Group group = (Group) editor.getDisplayedUser();
+               appendOverviewPart(body, group);
+               appendMembersPart(body, group);
        }
 
        /** Creates the general section */
-       protected void appendOverviewPart(Composite parent) {
+       protected void appendOverviewPart(Composite parent, final Group group) {
                FormToolkit tk = getManagedForm().getToolkit();
                Composite body = addSection(tk, parent, "Main information");
                GridLayout layout = new GridLayout(2, false);
                body.setLayout(layout);
 
-               Text distinguishedName = createLT(body, "Group Name",
-                               editor.getProperty(UserAdminConstants.KEY_UID));
+               final Text distinguishedName = createLT(body, "Group Name",
+                               UiAdminUtils.getProperty(group, UserAdminConstants.KEY_UID));
                distinguishedName.setEnabled(false);
 
                final Text commonName = createLT(body, "Common Name",
-                               editor.getProperty(UserAdminConstants.KEY_CN));
+                               UiAdminUtils.getProperty(group, UserAdminConstants.KEY_CN));
                commonName.setEnabled(false);
 
                // create form part (controller)
                AbstractFormPart part = new SectionPart((Section) body.getParent()) {
-                       public void commit(boolean onSave) {
-                               super.commit(onSave);
+
+                       private MainInfoListener listener;
+
+                       @Override
+                       public void initialize(IManagedForm form) {
+                               super.initialize(form);
+                               listener = editor.new MainInfoListener(this);
+                               userAdminWrapper.addListener(listener);
+                       }
+
+                       @Override
+                       public void dispose() {
+                               userAdminWrapper.removeListener(listener);
+                               super.dispose();
+                       }
+
+                       @Override
+                       public void refresh() {
+                               refreshFormTitle(group);
+                               distinguishedName.setText(UiAdminUtils.getProperty(group,
+                                               UserAdminConstants.KEY_UID));
+                               commonName.setText(UiAdminUtils.getProperty(group,
+                                               UserAdminConstants.KEY_CN));
+                               super.refresh();
                        }
                };
                getManagedForm().addPart(part);
        }
 
        /** Filtered table with members. Has drag & drop ability */
-       protected void appendMembersPart(Composite parent)
-                       throws RepositoryException {
+       protected void appendMembersPart(Composite parent, Group group) {
 
                FormToolkit tk = getManagedForm().getToolkit();
                Section section = tk.createSection(parent, Section.TITLE_BAR);
                section.setLayoutData(EclipseUiUtils.fillAll());
-               section.setText("Members of group "
-                               + editor.getProperty(UserAdminConstants.KEY_CN));
 
                // Composite body = tk.createComposite(section, SWT.NONE);
                Composite body = new Composite(section, SWT.NO_FOCUS);
                section.setClient(body);
                body.setLayoutData(EclipseUiUtils.fillAll());
 
-               createMemberPart(body);
+               UserTableViewer userTableViewerCmp = createMemberPart(body, group);
 
                // create form part (controller)
-               AbstractFormPart part = new SectionPart(section) {
-                       public void commit(boolean onSave) {
-                               super.commit(onSave);
-                       }
-               };
-
+               SectionPart part = new GroupMembersPart(section, userTableViewerCmp,
+                               group);
                getManagedForm().addPart(part);
+               addRemoveAbitily(part, userTableViewerCmp.getTableViewer(), group);
        }
 
-       // UI Objects
-       private UserTableViewer userTableViewerCmp;
-       private TableViewer userViewer;
-       private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
-
-       public void createMemberPart(Composite parent) {
+       public UserTableViewer createMemberPart(Composite parent, Group group) {
                parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
                // Define the displayed columns
+               List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
                columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
-               columnDefs.add(new ColumnDefinition(new UserNameLP(),
-                               "Distinguished Name", 240));
                columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Common Name",
                                150));
                columnDefs.add(new ColumnDefinition(new MailLP(), "Primary Mail", 150));
+               columnDefs.add(new ColumnDefinition(new UserNameLP(),
+                               "Distinguished Name", 240));
 
                // Create and configure the table
-               userTableViewerCmp = new MyUserTableViewer(parent, SWT.MULTI
+               UserTableViewer userViewerCmp = new MyUserTableViewer(parent, SWT.MULTI
                                | SWT.H_SCROLL | SWT.V_SCROLL, userAdminWrapper.getUserAdmin());
 
-               userTableViewerCmp.setColumnDefinitions(columnDefs);
-               userTableViewerCmp.populate(true, false);
-               // userTableViewerCmp.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
-               // false, false));
-               userTableViewerCmp.setLayoutData(EclipseUiUtils.fillAll());
+               userViewerCmp.setColumnDefinitions(columnDefs);
+               userViewerCmp.populate(true, false);
+               userViewerCmp.setLayoutData(EclipseUiUtils.fillAll());
 
-               // Links
-               userViewer = userTableViewerCmp.getTableViewer();
+               // Controllers
+               TableViewer userViewer = userViewerCmp.getTableViewer();
                userViewer.addDoubleClickListener(new UserTableDefaultDClickListener());
-               // Really?
-               userTableViewerCmp.refresh();
-
-               // Drag and drop
                int operations = DND.DROP_COPY | DND.DROP_MOVE;
                Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
                userViewer.addDropSupport(operations, tt,
-                               new GroupDropListener(userViewer, userAdminWrapper,
+                               new GroupDropListener(userAdminWrapper, userViewerCmp,
                                                (Group) editor.getDisplayedUser()));
+
+               return userViewerCmp;
        }
 
+       // Local viewers
+
        private class MyUserTableViewer extends UserTableViewer {
                private static final long serialVersionUID = 8467999509931900367L;
 
@@ -204,26 +218,127 @@ public class GroupMainPage extends FormPage implements ArgeoNames {
                }
        }
 
-       private void refreshFormTitle() throws RepositoryException {
-               getManagedForm().getForm().setText(
-                               editor.getProperty(UserAdminConstants.KEY_CN));
+       private void addRemoveAbitily(SectionPart sectionPart,
+                       TableViewer userViewer, Group group) {
+               Section section = sectionPart.getSection();
+               ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
+               ToolBar toolbar = toolBarManager.createControl(section);
+               final Cursor handCursor = new Cursor(section.getDisplay(),
+                               SWT.CURSOR_HAND);
+               toolbar.setCursor(handCursor);
+               toolbar.addDisposeListener(new DisposeListener() {
+                       private static final long serialVersionUID = 3882131405820522925L;
+
+                       public void widgetDisposed(DisposeEvent e) {
+                               if ((handCursor != null) && (handCursor.isDisposed() == false)) {
+                                       handCursor.dispose();
+                               }
+                       }
+               });
+
+               Action action = new RemoveMembershipAction(userViewer, group,
+                               "Remove selected items from this group",
+                               SecurityAdminImages.ICON_REMOVE_DESC);
+               toolBarManager.add(action);
+               toolBarManager.update(true);
+               section.setTextClient(toolbar);
+       }
+
+       private class RemoveMembershipAction extends Action {
+               private static final long serialVersionUID = -1337713097184522588L;
+
+               private final TableViewer userViewer;
+               private final Group group;
+
+               RemoveMembershipAction(TableViewer userViewer, Group group,
+                               String name, ImageDescriptor img) {
+                       super(name, img);
+                       this.userViewer = userViewer;
+                       this.group = group;
+               }
+
+               @Override
+               public void run() {
+                       ISelection selection = userViewer.getSelection();
+                       if (selection.isEmpty())
+                               return;
+
+                       @SuppressWarnings("unchecked")
+                       Iterator<User> it = ((IStructuredSelection) selection).iterator();
+                       List<User> users = new ArrayList<User>();
+                       // StringBuilder builder = new StringBuilder();
+                       while (it.hasNext()) {
+                               User currUser = it.next();
+                               // String groupName = UiAdminUtils.getUsername(currGroup);
+                               // builder.append(groupName).append("; ");
+                               users.add(currUser);
+                       }
+
+                       userAdminWrapper.beginTransactionIfNeeded();
+                       for (User user : users) {
+                               group.removeMember(user);
+                       }
+                       userAdminWrapper.notifyListeners(new UserAdminEvent(null,
+                                       UserAdminEvent.ROLE_CHANGED, group));
+               }
+       }
+
+       // LOCAL CONTROLLERS
+       private class GroupMembersPart extends SectionPart {
+               private final UserTableViewer userViewer;
+               private final Group group;
+
+               private GroupChangeListener listener;
+
+               public GroupMembersPart(Section section, UserTableViewer userViewer,
+                               Group group) {
+                       super(section);
+                       this.userViewer = userViewer;
+                       this.group = group;
+               }
+
+               @Override
+               public void initialize(IManagedForm form) {
+                       super.initialize(form);
+                       listener = editor.new GroupChangeListener(GroupMembersPart.this);
+                       userAdminWrapper.addListener(listener);
+               }
+
+               @Override
+               public void dispose() {
+                       userAdminWrapper.removeListener(listener);
+                       super.dispose();
+               }
+
+               @Override
+               public void refresh() {
+                       refreshFormTitle(group);
+                       getSection().setText(
+                                       "Members of group "
+                                                       + UiAdminUtils.getProperty(group,
+                                                                       UserAdminConstants.KEY_CN));
+                       userViewer.refresh();
+                       super.refresh();
+               }
        }
 
        /**
         * Defines this table as being a potential target to add group membership
-        * (roles) to this user
+        * (roles) to this group
         */
        private class GroupDropListener extends ViewerDropAdapter {
                private static final long serialVersionUID = 2893468717831451621L;
 
                private final UserAdminWrapper userAdminWrapper;
+               // private final UserTableViewer myUserViewerCmp;
                private final Group myGroup;
 
-               public GroupDropListener(Viewer viewer,
-                               UserAdminWrapper userAdminWrapper, Group group) {
-                       super(viewer);
+               public GroupDropListener(UserAdminWrapper userAdminWrapper,
+                               UserTableViewer userTableViewerCmp, Group group) {
+                       super(userTableViewerCmp.getTableViewer());
                        this.userAdminWrapper = userAdminWrapper;
                        this.myGroup = group;
+                       // this.myUserViewerCmp = userTableViewerCmp;
                }
 
                @Override
@@ -243,7 +358,7 @@ public class GroupMainPage extends FormPage implements ArgeoNames {
                        UserAdmin myUserAdmin = userAdminWrapper.getUserAdmin();
                        Role role = myUserAdmin.getRole(newUserName);
                        if (role.getType() == Role.USER) {
-                               // TODO check if the user is already member of this group
+                               // TODO check if the group is already member of this group
                                userAdminWrapper.beginTransactionIfNeeded();
                                User user = (User) role;
                                myGroup.addMember(user);
@@ -290,12 +405,17 @@ public class GroupMainPage extends FormPage implements ArgeoNames {
 
                @Override
                public boolean performDrop(Object data) {
-                       userTableViewerCmp.refresh();
+                       // myUserViewerCmp.refresh();
                        return true;
                }
        }
 
        // LOCAL HELPERS
+       private void refreshFormTitle(Group group) {
+               getManagedForm().getForm().setText(
+                               UiAdminUtils.getProperty(group, UserAdminConstants.KEY_CN));
+       }
+
        private Composite addSection(FormToolkit tk, Composite parent, String title) {
                Section section = tk.createSection(parent, Section.TITLE_BAR);
                GridData gd = EclipseUiUtils.fillWidth();
@@ -309,7 +429,7 @@ public class GroupMainPage extends FormPage implements ArgeoNames {
        }
 
        /** Creates label and text. */
-       protected Text createLT(Composite body, String label, String value) {
+       private Text createLT(Composite body, String label, String value) {
                FormToolkit toolkit = getManagedForm().getToolkit();
                Label lbl = toolkit.createLabel(body, label);
                lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
index 90ea372bd5e19384752777e7e5eb66cc26b45314..71eba27f646ba1b6bc0ccc0fa21593340cdbfea6 100644 (file)
@@ -20,18 +20,30 @@ import java.util.List;
 
 import org.argeo.ArgeoException;
 import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.argeo.security.ui.admin.internal.UiAdminUtils;
 import org.argeo.security.ui.admin.internal.UserAdminConstants;
 import org.argeo.security.ui.admin.internal.UserAdminWrapper;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.AbstractFormPart;
 import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.osgi.service.useradmin.Authorization;
 import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 import org.osgi.service.useradmin.UserAdminEvent;
+import org.osgi.service.useradmin.UserAdminListener;
 
 /** Editor for a user, might be a user or a group. */
 public class UserEditor extends FormEditor implements UserAdminConstants {
@@ -48,15 +60,16 @@ public class UserEditor extends FormEditor implements UserAdminConstants {
        private User user;
        private String username;
 
+       private NameChangeListener listener;
+
        public void init(IEditorSite site, IEditorInput input)
                        throws PartInitException {
                super.init(site, input);
                username = ((UserEditorInput) getEditorInput()).getUsername();
                user = (User) userAdmin.getRole(username);
 
-               String commonName = getProperty(KEY_CN);
-
-               setPartName(commonName != null ? commonName : "username");
+               listener = new NameChangeListener(user);
+               userAdminWrapper.addListener(listener);
 
                // TODO: following has been disabled because it causes NPE after a
                // login/logout on RAP
@@ -94,6 +107,10 @@ public class UserEditor extends FormEditor implements UserAdminConstants {
        }
 
        void updateEditorTitle(String title) {
+               if (title == null) {
+                       String commonName = UiAdminUtils.getProperty(user, KEY_CN);
+                       title = "".equals(commonName) ? commonName : user.getName();
+               }
                setPartName(title);
        }
 
@@ -108,14 +125,6 @@ public class UserEditor extends FormEditor implements UserAdminConstants {
                }
        }
 
-       protected String getProperty(String key) {
-               Object obj = user.getProperties().get(key);
-               if (obj != null)
-                       return (String) obj;
-               else
-                       return "";
-       }
-
        /**
         * Updates the property in the working copy. The transaction must be
         * explicitly committed to persist the update.
@@ -143,15 +152,76 @@ public class UserEditor extends FormEditor implements UserAdminConstants {
                return false;
        }
 
-       public void refresh() {
-
-       }
-
        @Override
        public void dispose() {
+               userAdminWrapper.removeListener(listener);
                super.dispose();
        }
 
+       // CONTROLERS FOR THIS EDITOR AND ITS PAGES
+
+       class NameChangeListener implements UserAdminListener {
+
+               private final User user;
+
+               public NameChangeListener(User user) {
+                       this.user = user;
+               }
+
+               @Override
+               public void roleChanged(UserAdminEvent event) {
+                       Role changedRole = event.getRole();
+                       if (changedRole == null || changedRole.equals(user))
+                               updateEditorTitle(null);
+               }
+       }
+
+       class MainInfoListener implements UserAdminListener {
+               private final AbstractFormPart part;
+
+               public MainInfoListener(AbstractFormPart part) {
+                       this.part = part;
+               }
+
+               @Override
+               public void roleChanged(UserAdminEvent event) {
+                       // Rollback
+                       if (event.getRole() == null)
+                               part.markStale();
+               }
+       }
+
+       class GroupChangeListener implements UserAdminListener {
+               private final AbstractFormPart part;
+
+               public GroupChangeListener(AbstractFormPart part) {
+                       this.part = part;
+               }
+
+               @Override
+               public void roleChanged(UserAdminEvent event) {
+                       // always mark as stale
+                       part.markStale();
+               }
+       }
+
+       /** Registers a listener that will notify this part */
+       class FormPartML implements ModifyListener {
+               private static final long serialVersionUID = 6299808129505381333L;
+               private AbstractFormPart formPart;
+
+               public FormPartML(AbstractFormPart generalPart) {
+                       this.formPart = generalPart;
+               }
+
+               public void modifyText(ModifyEvent e) {
+                       // Discard event when the control does not have the focus, typically
+                       // to avoid all editors being marked as dirty during a Rollback
+                       if (((Control) e.widget).isFocusControl())
+                               formPart.markDirty();
+               }
+       }
+
        /* DEPENDENCY INJECTION */
        public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
                this.userAdminWrapper = userAdminWrapper;
index 9f186811118bb47e6f8902f1bf58a7917b41671d..013519cbe884b765aabca52725e955198aed4adf 100644 (file)
 package org.argeo.security.ui.admin.internal.parts;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 
 import org.argeo.ArgeoException;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.jcr.ArgeoNames;
+import org.argeo.security.ui.admin.SecurityAdminImages;
 import org.argeo.security.ui.admin.internal.ColumnDefinition;
+import org.argeo.security.ui.admin.internal.UiAdminUtils;
 import org.argeo.security.ui.admin.internal.UserAdminConstants;
 import org.argeo.security.ui.admin.internal.UserAdminWrapper;
 import org.argeo.security.ui.admin.internal.UserTableViewer;
+import org.argeo.security.ui.admin.internal.parts.UserEditor.GroupChangeListener;
+import org.argeo.security.ui.admin.internal.parts.UserEditor.MainInfoListener;
 import org.argeo.security.ui.admin.internal.providers.CommonNameLP;
 import org.argeo.security.ui.admin.internal.providers.RoleIconLP;
 import org.argeo.security.ui.admin.internal.providers.UserNameLP;
 import org.argeo.security.ui.admin.internal.providers.UserTableDefaultDClickListener;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerDropAdapter;
@@ -39,13 +48,17 @@ import org.eclipse.swt.dnd.DropTargetEvent;
 import org.eclipse.swt.dnd.TextTransfer;
 import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Cursor;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.ui.forms.AbstractFormPart;
 import org.eclipse.ui.forms.IManagedForm;
 import org.eclipse.ui.forms.SectionPart;
@@ -60,17 +73,13 @@ import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 import org.osgi.service.useradmin.UserAdminEvent;
 
-/** Display/edit the properties common to all users */
+/** Display/edit the properties of a given user */
 public class UserMainPage extends FormPage implements ArgeoNames {
-       final static String ID = "argeoUserEditor.mainPage";
-
-       // private final static Log log = LogFactory.getLog(UserMainPage.class);
+       final static String ID = "UserEditor.mainPage";
 
        private final UserEditor editor;
        private UserAdminWrapper userAdminWrapper;
 
-       private char[] newPassword;
-
        // Local configuration
        private final int PRE_TITLE_INDENT = 10;
 
@@ -80,62 +89,65 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                this.userAdminWrapper = userAdminWrapper;
        }
 
-       public String getNewPassword() {
-               if (newPassword != null)
-                       return new String(newPassword);
-               else
-                       return null;
-       }
-
-       public void resetNewPassword() {
-               if (newPassword != null)
-                       Arrays.fill(newPassword, 'x');
-               newPassword = null;
-       }
-
        protected void createFormContent(final IManagedForm mf) {
                ScrolledForm form = mf.getForm();
-               // Form page main title
-               form.setText(editor.getProperty(UserAdminConstants.KEY_CN));
-
-               // Body
                Composite body = form.getBody();
-               GridLayout mainLayout = new GridLayout(1, true);
+               GridLayout mainLayout = new GridLayout();
                body.setLayout(mainLayout);
-               appendOverviewPart(body);
-               appendPasswordPart(body);
-               appendMemberOfPart(body);
+               User user = editor.getDisplayedUser();
+               appendOverviewPart(body, user);
+               // Remove to ability to force the password for his own user. The user
+               // must then use the change pwd feature
+               if (!UiAdminUtils.isCurrentUser(user))
+                       appendPasswordPart(body, user);
+               appendMemberOfPart(body, user);
        }
 
        /** Creates the general section */
-       protected void appendOverviewPart(Composite parent) {
+       private void appendOverviewPart(Composite parent, final User user) {
                FormToolkit tk = getManagedForm().getToolkit();
-               Composite body = addSection(tk, parent, "Main information");
+
+               Section section = addSection(tk, parent, "Main information");
+               Composite body = (Composite) section.getClient();
                body.setLayout(new GridLayout(2, false));
 
-               Text distinguishedName = createLT(body, "User Name",
-                               editor.getProperty(UserAdminConstants.KEY_UID));
+               final Text distinguishedName = createLT(tk, body, "User Name",
+                               UiAdminUtils.getProperty(user, UserAdminConstants.KEY_UID));
                distinguishedName.setEnabled(false);
 
-               final Text commonName = createLT(body, "Common Name",
-                               editor.getProperty(UserAdminConstants.KEY_CN));
+               final Text commonName = createLT(tk, body, "Common Name",
+                               UiAdminUtils.getProperty(user, UserAdminConstants.KEY_CN));
                commonName.setEnabled(false);
 
-               final Text firstName = createLT(body, "First name",
-                               editor.getProperty(UserAdminConstants.KEY_FIRSTNAME));
+               final Text firstName = createLT(tk, body, "First name",
+                               UiAdminUtils
+                                               .getProperty(user, UserAdminConstants.KEY_FIRSTNAME));
 
-               final Text lastName = createLT(body, "Last name",
-                               editor.getProperty(UserAdminConstants.KEY_LASTNAME));
+               final Text lastName = createLT(tk, body, "Last name",
+                               UiAdminUtils.getProperty(user, UserAdminConstants.KEY_LASTNAME));
 
-               final Text email = createLT(body, "Email",
-                               editor.getProperty(UserAdminConstants.KEY_MAIL));
+               final Text email = createLT(tk, body, "Email",
+                               UiAdminUtils.getProperty(user, UserAdminConstants.KEY_MAIL));
 
                // create form part (controller)
                AbstractFormPart part = new SectionPart((Section) body.getParent()) {
+                       private MainInfoListener listener;
+
+                       @Override
+                       public void initialize(IManagedForm form) {
+                               super.initialize(form);
+                               listener = editor.new MainInfoListener(this);
+                               userAdminWrapper.addListener(listener);
+                       }
+
+                       @Override
+                       public void dispose() {
+                               userAdminWrapper.removeListener(listener);
+                               super.dispose();
+                       }
+
                        public void commit(boolean onSave) {
-                               // TODO check changed ?
                                // TODO Sanity checks
-
                                editor.setProperty(UserAdminConstants.KEY_FIRSTNAME,
                                                firstName.getText());
                                editor.setProperty(UserAdminConstants.KEY_LASTNAME,
@@ -150,8 +162,26 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                                // email.getText());
                                super.commit(onSave);
                        }
+
+                       @Override
+                       public void refresh() {
+                               distinguishedName.setText(UiAdminUtils.getProperty(user,
+                                               UserAdminConstants.KEY_UID));
+                               commonName.setText(UiAdminUtils.getProperty(user,
+                                               UserAdminConstants.KEY_CN));
+                               firstName.setText(UiAdminUtils.getProperty(user,
+                                               UserAdminConstants.KEY_FIRSTNAME));
+                               lastName.setText(UiAdminUtils.getProperty(user,
+                                               UserAdminConstants.KEY_LASTNAME));
+                               email.setText(UiAdminUtils.getProperty(user,
+                                               UserAdminConstants.KEY_MAIL));
+                               refreshFormTitle(user);
+                               super.refresh();
+                       }
                };
 
+               // Improve this: automatically generate CN when first or last name
+               // changes
                ModifyListener cnML = new ModifyListener() {
                        private static final long serialVersionUID = 4298649222869835486L;
 
@@ -168,37 +198,35 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                };
                firstName.addModifyListener(cnML);
                lastName.addModifyListener(cnML);
-               firstName.addModifyListener(new FormPartML(part));
-               lastName.addModifyListener(new FormPartML(part));
-               email.addModifyListener(new FormPartML(part));
+
+               ModifyListener defaultListener = editor.new FormPartML(part);
+               firstName.addModifyListener(defaultListener);
+               lastName.addModifyListener(defaultListener);
+               email.addModifyListener(defaultListener);
                getManagedForm().addPart(part);
        }
 
        /** Creates the password section */
-       protected void appendPasswordPart(Composite parent) {
+       private void appendPasswordPart(Composite parent, final User user) {
                FormToolkit tk = getManagedForm().getToolkit();
-               Composite body = addSection(tk, parent, "Password");
-
-               // Section section = tk.createSection(parent, Section.TITLE_BAR);
-               // section.setLayoutData(EclipseUiUtils.fillWidth());
-               // section.setText("Password");
-               // Composite body = tk.createComposite(section, SWT.NO_FOCUS);
-               // section.setClient(body);
-               // body.setLayoutData(EclipseUiUtils.fillWidth());
-
+               Section section = addSection(tk, parent, "Password");
+               Composite body = (Composite) section.getClient();
                body.setLayout(new GridLayout(2, false));
+
                // add widgets (view)
-               final Text password1 = createLP(body, "New password", "");
-               final Text password2 = createLP(body, "Repeat password", "");
+               final Text password1 = createLP(tk, body, "New password", "");
+               final Text password2 = createLP(tk, body, "Repeat password", "");
+
                // create form part (controller)
                AbstractFormPart part = new SectionPart((Section) body.getParent()) {
-
+                       @SuppressWarnings("unchecked")
                        public void commit(boolean onSave) {
                                if (!password1.getText().equals("")
                                                || !password2.getText().equals("")) {
                                        if (password1.getText().equals(password2.getText())) {
-                                               newPassword = password1.getText().toCharArray();
-                                               // TODO real set password
+                                               char[] newPassword = password1.getText().toCharArray();
+                                               userAdminWrapper.beginTransactionIfNeeded();
+                                               user.getCredentials().put(null, newPassword);
                                                password1.setText("");
                                                password2.setText("");
                                                super.commit(onSave);
@@ -209,80 +237,185 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                                        }
                                }
                        }
-
                };
-               password1.addModifyListener(new FormPartML(part));
-               password2.addModifyListener(new FormPartML(part));
+               ModifyListener defaultListener = editor.new FormPartML(part);
+               password1.addModifyListener(defaultListener);
+               password2.addModifyListener(defaultListener);
                getManagedForm().addPart(part);
        }
 
-       private UserTableViewer userTableViewerCmp;
-       private TableViewer userViewer;
-
-       private void appendMemberOfPart(Composite parent) {
+       private UserTableViewer appendMemberOfPart(Composite parent, User user) {
                FormToolkit tk = getManagedForm().getToolkit();
-               Composite body = addSection(tk, parent, "Roles");
+               Section section = addSection(tk, parent, "Roles");
+               Composite body = (Composite) section.getClient();
                body.setLayout(EclipseUiUtils.noSpaceGridLayout());
 
-               // Define the displayed columns
+               // Displayed columns
                List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
                columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
-               columnDefs.add(new ColumnDefinition(new UserNameLP(),
-                               "Distinguished Name", 300));
                columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Common Name",
                                150));
+               columnDefs.add(new ColumnDefinition(new UserNameLP(),
+                               "Distinguished Name", 300));
 
                // Create and configure the table
-               userTableViewerCmp = new MyUserTableViewer(body, SWT.MULTI
-                               | SWT.H_SCROLL | SWT.V_SCROLL, userAdminWrapper.getUserAdmin());
+               final UserTableViewer userViewerCmp = new MyUserTableViewer(body,
+                               SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL,
+                               userAdminWrapper.getUserAdmin(), user);
 
-               userTableViewerCmp.setColumnDefinitions(columnDefs);
-               userTableViewerCmp.populate(true, false);
+               userViewerCmp.setColumnDefinitions(columnDefs);
+               userViewerCmp.populate(true, false);
                GridData gd = EclipseUiUtils.fillAll();
                gd.heightHint = 300;
-               userTableViewerCmp.setLayoutData(gd);
+               userViewerCmp.setLayoutData(gd);
 
-               // Links
-               userViewer = userTableViewerCmp.getTableViewer();
+               // Controllers
+               TableViewer userViewer = userViewerCmp.getTableViewer();
                userViewer.addDoubleClickListener(new UserTableDefaultDClickListener());
-               // Really?
-               userTableViewerCmp.refresh();
-
-               // Drag and drop
                int operations = DND.DROP_COPY | DND.DROP_MOVE;
                Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
-               userViewer.addDropSupport(operations, tt, new GroupDropListener(
-                               userViewer, userAdminWrapper.getUserAdmin(), editor.getDisplayedUser()));
+               GroupDropListener dropL = new GroupDropListener(userAdminWrapper,
+                               userViewer, user);
+               userViewer.addDropSupport(operations, tt, dropL);
+
+               SectionPart part = new SectionPart((Section) body.getParent()) {
+
+                       private GroupChangeListener listener;
+
+                       @Override
+                       public void initialize(IManagedForm form) {
+                               super.initialize(form);
+                               listener = editor.new GroupChangeListener(this);
+                               userAdminWrapper.addListener(listener);
+                       }
+
+                       public void commit(boolean onSave) {
+                               super.commit(onSave);
+                       }
+
+                       @Override
+                       public void dispose() {
+                               userAdminWrapper.removeListener(listener);
+                               super.dispose();
+                       }
 
+                       @Override
+                       public void refresh() {
+                               userViewerCmp.refresh();
+                               super.refresh();
+                       }
+               };
+               getManagedForm().addPart(part);
+               addRemoveAbitily(part, userViewer, user);
+               return userViewerCmp;
        }
 
        private class MyUserTableViewer extends UserTableViewer {
                private static final long serialVersionUID = 8467999509931900367L;
 
+               private final User user;
+
                public MyUserTableViewer(Composite parent, int style,
-                               UserAdmin userAdmin) {
+                               UserAdmin userAdmin, User user) {
                        super(parent, style, userAdmin, true);
+                       this.user = user;
                }
 
                @Override
                protected List<User> listFilteredElements(String filter) {
-                       return (List<User>) editor.getFlatGroups(null);
+                       List<User> users = (List<User>) editor.getFlatGroups(null);
+                       if (users.contains(user))
+                               users.remove(user);
+                       return users;
+               }
+       }
+
+       private void addRemoveAbitily(SectionPart sectionPart,
+                       TableViewer userViewer, User user) {
+               Section section = sectionPart.getSection();
+               ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
+               ToolBar toolbar = toolBarManager.createControl(section);
+               final Cursor handCursor = new Cursor(section.getDisplay(),
+                               SWT.CURSOR_HAND);
+               toolbar.setCursor(handCursor);
+               toolbar.addDisposeListener(new DisposeListener() {
+                       private static final long serialVersionUID = 3882131405820522925L;
+
+                       public void widgetDisposed(DisposeEvent e) {
+                               if ((handCursor != null) && (handCursor.isDisposed() == false)) {
+                                       handCursor.dispose();
+                               }
+                       }
+               });
+
+               Action action = new RemoveMembershipAction(userViewer, user,
+                               "Remove selected groups", SecurityAdminImages.ICON_REMOVE_DESC);
+               toolBarManager.add(action);
+               toolBarManager.update(true);
+               section.setTextClient(toolbar);
+       }
+
+       private class RemoveMembershipAction extends Action {
+               private static final long serialVersionUID = -1337713097184522588L;
+
+               private final TableViewer userViewer;
+               private final User user;
+
+               RemoveMembershipAction(TableViewer userViewer, User user, String name,
+                               ImageDescriptor img) {
+                       super(name, img);
+                       this.userViewer = userViewer;
+                       this.user = user;
+               }
+
+               @Override
+               public void run() {
+                       ISelection selection = userViewer.getSelection();
+                       if (selection.isEmpty())
+                               return;
+
+                       @SuppressWarnings("unchecked")
+                       Iterator<Group> it = ((IStructuredSelection) selection).iterator();
+                       List<Group> groups = new ArrayList<Group>();
+                       // StringBuilder builder = new StringBuilder();
+                       while (it.hasNext()) {
+                               Group currGroup = it.next();
+                               // String groupName = UiAdminUtils.getUsername(currGroup);
+                               // builder.append(groupName).append("; ");
+                               groups.add(currGroup);
+                       }
+
+                       // if (!MessageDialog.openQuestion(
+                       // HandlerUtil.getActiveShell(event),
+                       // "Re",
+                       // "Are you sure that you want to delete these users?\n"
+                       // + builder.substring(0, builder.length() - 2)))
+                       // return null;
+
+                       userAdminWrapper.beginTransactionIfNeeded();
+                       for (Group group : groups) {
+                               group.removeMember(user);
+                               // sectionPart.refresh();
+                               userAdminWrapper.notifyListeners(new UserAdminEvent(null,
+                                               UserAdminEvent.ROLE_CHANGED, group));
+                       }
                }
        }
 
        /**
-        * Defines this table as being a potential target to add group membership
+        * Defines the table as being a potential target to add group memberships
         * (roles) to this user
         */
        private class GroupDropListener extends ViewerDropAdapter {
                private static final long serialVersionUID = 2893468717831451621L;
 
-               private final UserAdmin myUserAdmin;
+               private final UserAdminWrapper myUserAdminWrapper;
                private final User myUser;
 
-               public GroupDropListener(Viewer viewer, UserAdmin userAdmin, User user) {
-                       super(viewer);
-                       this.myUserAdmin = userAdmin;
+               public GroupDropListener(UserAdminWrapper userAdminWrapper,
+                               Viewer userViewer, User user) {
+                       super(userViewer);
+                       this.myUserAdminWrapper = userAdminWrapper;
                        this.myUser = user;
                }
 
@@ -298,14 +431,15 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                @Override
                public void drop(DropTargetEvent event) {
                        String name = (String) event.data;
+                       UserAdmin myUserAdmin = myUserAdminWrapper.getUserAdmin();
                        Role role = myUserAdmin.getRole(name);
                        // TODO this check should be done before.
                        if (role.getType() == Role.GROUP) {
                                // TODO check if the user is already member of this group
-                               userAdminWrapper.beginTransactionIfNeeded();
+                               myUserAdminWrapper.beginTransactionIfNeeded();
                                Group group = (Group) role;
                                group.addMember(myUser);
-                               userAdminWrapper.notifyListeners(new UserAdminEvent(null,
+                               myUserAdminWrapper.notifyListeners(new UserAdminEvent(null,
                                                UserAdminEvent.ROLE_CHANGED, group));
                        }
                        super.drop(event);
@@ -313,28 +447,36 @@ public class UserMainPage extends FormPage implements ArgeoNames {
 
                @Override
                public boolean performDrop(Object data) {
-                       userTableViewerCmp.refresh();
+                       // userTableViewerCmp.refresh();
                        return true;
                }
        }
 
        // LOCAL HELPERS
+       private void refreshFormTitle(User group) {
+               getManagedForm().getForm().setText(
+                               UiAdminUtils.getProperty(group, UserAdminConstants.KEY_CN));
+       }
+
        /** Appends a section with a title */
-       private Composite addSection(FormToolkit tk, Composite parent, String title) {
+       private Section addSection(FormToolkit tk, Composite parent, String title) {
                Section section = tk.createSection(parent, Section.TITLE_BAR);
                GridData gd = EclipseUiUtils.fillWidth();
                gd.verticalAlignment = PRE_TITLE_INDENT;
                section.setLayoutData(gd);
                section.setText(title);
+               // section.getMenu().setVisible(true);
+
                Composite body = tk.createComposite(section, SWT.WRAP);
                body.setLayoutData(EclipseUiUtils.fillAll());
                section.setClient(body);
-               return body;
+
+               return section;
        }
 
        /** Creates label and multiline text. */
-       protected Text createLMT(Composite body, String label, String value) {
-               FormToolkit toolkit = getManagedForm().getToolkit();
+       Text createLMT(FormToolkit toolkit, Composite body, String label,
+                       String value) {
                Label lbl = toolkit.createLabel(body, label);
                lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
                Text text = toolkit.createText(body, value, SWT.BORDER | SWT.MULTI);
@@ -343,8 +485,8 @@ public class UserMainPage extends FormPage implements ArgeoNames {
        }
 
        /** Creates label and password. */
-       protected Text createLP(Composite body, String label, String value) {
-               FormToolkit toolkit = getManagedForm().getToolkit();
+       Text createLP(FormToolkit toolkit, Composite body, String label,
+                       String value) {
                Label lbl = toolkit.createLabel(body, label);
                lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
                Text text = toolkit.createText(body, value, SWT.BORDER | SWT.PASSWORD);
@@ -353,25 +495,12 @@ public class UserMainPage extends FormPage implements ArgeoNames {
        }
 
        /** Creates label and text. */
-       protected Text createLT(Composite body, String label, String value) {
-               FormToolkit toolkit = getManagedForm().getToolkit();
+       Text createLT(FormToolkit toolkit, Composite body, String label,
+                       String value) {
                Label lbl = toolkit.createLabel(body, label);
                lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
                Text text = toolkit.createText(body, value, SWT.BORDER);
                text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
                return text;
        }
-
-       private class FormPartML implements ModifyListener {
-               private static final long serialVersionUID = 6299808129505381333L;
-               private AbstractFormPart formPart;
-
-               public FormPartML(AbstractFormPart generalPart) {
-                       this.formPart = generalPart;
-               }
-
-               public void modifyText(ModifyEvent e) {
-                       formPart.markDirty();
-               }
-       }
 }
\ No newline at end of file