X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=security%2Fplugins%2Forg.argeo.security.ui.admin%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fui%2Fadmin%2Fviews%2FUsersView.java;h=41d8ed036bae2cb18a17246f8b9b7c899efca8ad;hb=8308e5b33eb13edb35bfa35569d73b6bbe43ff73;hp=77b718e1262648d25b5c69844780c44411a7e28b;hpb=fb4f7c451ea7d9025f7cf7fe032020f229df794a;p=lgpl%2Fargeo-commons.git diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java index 77b718e12..41d8ed036 100644 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java +++ b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.argeo.security.ui.admin.views; import java.util.ArrayList; @@ -5,74 +20,278 @@ import java.util.List; import javax.jcr.Node; import javax.jcr.NodeIterator; +import javax.jcr.Property; import javax.jcr.RepositoryException; import javax.jcr.Session; +import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; import javax.jcr.observation.EventListener; -import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; +import javax.jcr.query.qom.Constraint; +import javax.jcr.query.qom.DynamicOperand; +import javax.jcr.query.qom.Ordering; +import javax.jcr.query.qom.QueryObjectModel; +import javax.jcr.query.qom.QueryObjectModelFactory; +import javax.jcr.query.qom.Selector; +import javax.jcr.query.qom.StaticOperand; import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils; +import org.argeo.eclipse.ui.utils.CommandUtils; +import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; +import org.argeo.jcr.JcrUtils; import org.argeo.security.ui.admin.SecurityAdminPlugin; import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor; -import org.eclipse.core.commands.Command; -import org.eclipse.core.commands.IParameter; -import org.eclipse.core.commands.Parameterization; -import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.commands.ICommandService; -import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.swt.widgets.Text; import org.eclipse.ui.part.ViewPart; /** List all users. */ -public class UsersView extends ViewPart implements ArgeoNames, ArgeoTypes, - EventListener { - public final static String ID = "org.argeo.security.ui.admin.adminUsersView"; +public class UsersView extends ViewPart implements ArgeoNames { + public final static String ID = SecurityAdminPlugin.PLUGIN_ID + + ".adminUsersView"; private TableViewer viewer; + private Text filterTxt; + private final static String FILTER_HELP_MSG = "Enter filter criterion " + + "separated by a space (on user ID, name and E-mail"; + private final static Image FILTER_RESET = SecurityAdminPlugin + .getImageDescriptor("icons/users.gif").createImage(); + private Session session; + private UserStructureListener userStructureListener; + private UserPropertiesListener userPropertiesListener; + + private Font italic; + private Font bold; + @Override public void createPartControl(Composite parent) { - viewer = new TableViewer(createTable(parent)); + italic = EclipseUiUtils.getItalicFont(parent); + bold = EclipseUiUtils.getBoldFont(parent); + + // Main Layout + GridLayout layout = new GridLayout(1, false); + parent.setLayout(layout); + createFilterPart(parent); + + viewer = createTableViewer(parent); + EclipseUiSpecificUtils.enableToolTipSupport(viewer); viewer.setContentProvider(new UsersContentProvider()); - viewer.setLabelProvider(new UsersLabelProvider()); viewer.addDoubleClickListener(new ViewDoubleClickListener()); - viewer.setInput(getViewSite()); + getViewSite().setSelectionProvider(viewer); + + userStructureListener = new UserStructureListener(); + JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED + | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null); + userPropertiesListener = new UserPropertiesListener(); + JcrUtils.addListener(session, userStructureListener, + Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED + | Event.PROPERTY_REMOVED, + ArgeoJcrConstants.PEOPLE_BASE_PATH, + ArgeoTypes.ARGEO_USER_PROFILE); + + refreshFilteredList(); } - protected Table createTable(Composite parent) { + protected TableViewer createTableViewer(final Composite parent) { + Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + TableViewer viewer = new TableViewer(table); table.setLinesVisible(true); table.setHeaderVisible(true); - TableColumn column = new TableColumn(table, SWT.LEFT, 0); - column.setText("User"); - column.setWidth(50); - column = new TableColumn(table, SWT.LEFT, 1); - column.setText("First Name"); - column.setWidth(100); - column = new TableColumn(table, SWT.LEFT, 2); - column.setText("Last Name"); - column.setWidth(100); - column = new TableColumn(table, SWT.LEFT, 3); - column.setText("E-mail"); - column.setWidth(100); - return table; + + // pass a mapping between col index and property name to the comparator. + List propertiesList = new ArrayList(); + + // User ID + TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setText("User ID"); + column.getColumn().setWidth(100); + column.getColumn().addSelectionListener(getSelectionAdapter(0)); + propertiesList.add(ARGEO_USER_ID); + column.setLabelProvider(new CLProvider() { + public String getText(Object elem) { + return getProperty(elem, ARGEO_USER_ID); + // if (username.equals(session.getUserID())) + // return "[" + username + "]"; + // else + // return username; + } + }); + + // Displayed name + column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setText("Name"); + column.getColumn().setWidth(150); + column.getColumn().addSelectionListener(getSelectionAdapter(1)); + propertiesList.add(Property.JCR_TITLE); + column.setLabelProvider(new CLProvider() { + public String getText(Object elem) { + return getProperty(elem, Property.JCR_TITLE); + } + }); + + // E-mail + column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setText("E-mail"); + column.getColumn().setWidth(150); + column.getColumn().addSelectionListener(getSelectionAdapter(2)); + propertiesList.add(ARGEO_PRIMARY_EMAIL); + column.setLabelProvider(new CLProvider() { + public String getText(Object elem) { + return getProperty(elem, ARGEO_PRIMARY_EMAIL); + } + }); + + // Description + column = new TableViewerColumn(viewer, SWT.NONE); + column.getColumn().setText("Description"); + column.getColumn().setWidth(200); + column.getColumn().addSelectionListener(getSelectionAdapter(3)); + propertiesList.add(Property.JCR_DESCRIPTION); + column.setLabelProvider(new CLProvider() { + public String getText(Object elem) { + return getProperty(elem, Property.JCR_DESCRIPTION); + } + }); + + viewer.setComparator(new UsersViewerComparator(propertiesList)); + + return viewer; + } + + private class CLProvider extends ColumnLabelProvider { + + public String getToolTipText(Object element) { + return getText(element); + } + + @Override + public Font getFont(Object elem) { + // self + String username = getProperty(elem, ARGEO_USER_ID); + if (username.equals(session.getUserID())) + return bold; + + // disabled + try { + Node userProfile = (Node) elem; + // Node userProfile = userHome.getNode(ARGEO_PROFILE); + if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) + return italic; + else + return null; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get font for " + username, e); + } + } + + } + + private SelectionAdapter getSelectionAdapter(final int index) { + SelectionAdapter selectionAdapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + UsersViewerComparator comparator = (UsersViewerComparator) viewer + .getComparator(); + + if (index == comparator.getSortColumn()) { + comparator.setAscending(!comparator.isAscending()); + } + comparator.setSortColumn(index); + viewer.getTable().setSortColumn( + viewer.getTable().getColumn(index)); + viewer.getTable().setSortDirection( + comparator.isAscending() ? SWT.UP : SWT.DOWN); + viewer.refresh(false); + } + }; + return selectionAdapter; + } + + private class UsersViewerComparator extends ViewerComparator { + + private List propertyList; + private int sortColumn = 0; + private boolean ascending = true; + // use this to enable two levels sort + @SuppressWarnings("unused") + private int lastSortColumn = 0; + @SuppressWarnings("unused") + private boolean lastAscending = true; + + public UsersViewerComparator(List propertyList) { + super(); + this.propertyList = propertyList; + } + + public int compare(Viewer viewer, Object e1, Object e2) { + String s1 = getProperty(e1, propertyList.get(sortColumn)); + String s2 = getProperty(e2, propertyList.get(sortColumn)); + int result = super.compare(viewer, s1, s2); + return ascending ? result : (-1) * result; + } + + /** + * @return Returns the sortColumn. + */ + public int getSortColumn() { + return sortColumn; + } + + /** + * @param sortColumn + * The sortColumn to set. + */ + public void setSortColumn(int sortColumn) { + if (this.sortColumn != sortColumn) { + lastSortColumn = this.sortColumn; + lastAscending = this.ascending; + this.sortColumn = sortColumn; + } + } + + /** + * @return Returns the ascending. + */ + public boolean isAscending() { + return ascending; + } + + /** + * @param ascending + * The ascending to set. + */ + public void setAscending(boolean ascending) { + this.ascending = ascending; + } } @Override @@ -80,6 +299,13 @@ public class UsersView extends ViewPart implements ArgeoNames, ArgeoTypes, viewer.getTable().setFocus(); } + @Override + public void dispose() { + JcrUtils.removeListenerQuietly(session, userStructureListener); + JcrUtils.removeListenerQuietly(session, userPropertiesListener); + super.dispose(); + } + public void setSession(Session session) { this.session = session; } @@ -88,73 +314,68 @@ public class UsersView extends ViewPart implements ArgeoNames, ArgeoTypes, viewer.refresh(); } - @Override - public void onEvent(EventIterator events) { - viewer.refresh(); + protected String getProperty(Node userProfile, String name) + throws RepositoryException { + return userProfile.hasProperty(name) ? userProfile.getProperty(name) + .getString() : ""; } - private class UsersContentProvider implements IStructuredContentProvider { - - public Object[] getElements(Object inputElement) { - try { - Query query = session - .getWorkspace() - .getQueryManager() - .createQuery( - "select [" + ARGEO_PROFILE + "] from [" - + ARGEO_USER_HOME + "]", Query.JCR_SQL2); - NodeIterator nit = query.execute().getNodes(); - List userProfiles = new ArrayList(); - while (nit.hasNext()) { - userProfiles.add(nit.nextNode()); - } - return userProfiles.toArray(); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot list users", e); - } - // return userAdminService.listUsers().toArray(); + protected String getProperty(Object element, String name) { + try { + Node userProfile = (Node) element; + // Node userProfile = userHome.getNode(ARGEO_PROFILE); + return userProfile.hasProperty(name) ? userProfile + .getProperty(name).getString() : ""; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get property " + name, e); } + } - public void dispose() { - } + private class UserStructureListener implements EventListener { - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + @Override + public void onEvent(EventIterator events) { + viewer.refresh(); } + } + + private class UserPropertiesListener implements EventListener { + @Override + public void onEvent(EventIterator events) { + viewer.refresh(); + } } - private class UsersLabelProvider extends LabelProvider implements - ITableLabelProvider { - public String getColumnText(Object element, int columnIndex) { - try { - Node userHome = (Node) element; - switch (columnIndex) { - case 0: - String userName = userHome.getProperty(ARGEO_USER_ID) - .getString(); - if (userName.equals(session.getUserID())) - return "[" + userName + "]"; - else - return userName; - case 1: - return userHome.getNode(ARGEO_PROFILE) - .getProperty(ARGEO_FIRST_NAME).getString(); - case 2: - return userHome.getNode(ARGEO_PROFILE) - .getProperty(ARGEO_LAST_NAME).getString(); - case 3: - return userHome.getNode(ARGEO_PROFILE) - .getProperty(ARGEO_PRIMARY_EMAIL).getString(); - default: - throw new ArgeoException("Unmanaged column " + columnIndex); - } - } catch (RepositoryException e) { - throw new ArgeoException("Cannot get text", e); - } + private class UsersContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object inputElement) { + return (Object[]) inputElement; + + // try { + // Query query = session + // .getWorkspace() + // .getQueryManager() + // .createQuery( + // "select * from [" + // + ArgeoTypes.ARGEO_USER_PROFILE + "]", + // Query.JCR_SQL2); + // NodeIterator nit = query.execute().getNodes(); + // List userProfiles = new ArrayList(); + // while (nit.hasNext()) { + // userProfiles.add(nit.nextNode()); + // } + // return userProfiles.toArray(); + // } catch (RepositoryException e) { + // throw new ArgeoException("Cannot list users", e); + // } + // // return userAdminService.listUsers().toArray(); + } + + public void dispose() { } - public Image getColumnImage(Object element, int columnIndex) { - return null; + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } @@ -167,38 +388,121 @@ public class UsersView extends ViewPart implements ArgeoNames, ArgeoTypes, Object obj = ((IStructuredSelection) evt.getSelection()) .getFirstElement(); if (obj instanceof Node) { - IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench(); - IHandlerService handlerService = (IHandlerService) iw - .getService(IHandlerService.class); try { String username = ((Node) obj).getProperty(ARGEO_USER_ID) .getString(); String commandId = OpenArgeoUserEditor.COMMAND_ID; String paramName = OpenArgeoUserEditor.PARAM_USERNAME; - - // TODO: factorize this - // execute related command - IWorkbenchWindow window = iw.getActiveWorkbenchWindow(); - ICommandService cmdService = (ICommandService) window - .getService(ICommandService.class); - Command cmd = cmdService.getCommand(commandId); - ArrayList parameters = new ArrayList(); - IParameter iparam = cmd.getParameter(paramName); - Parameterization param = new Parameterization(iparam, - username); - parameters.add(param); - ParameterizedCommand pc = new ParameterizedCommand(cmd, - parameters.toArray(new Parameterization[parameters - .size()])); - handlerService = (IHandlerService) window - .getService(IHandlerService.class); - handlerService.executeCommand(pc, null); - } catch (Exception e) { - throw new ArgeoException("Cannot open editor", e); + CommandUtils.callCommand(commandId, paramName, username); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot open user editor", e); } + } + } + } + + /* MANAGE FILTER */ + private void createFilterPart(Composite parent) { + Composite header = new Composite(parent, SWT.FILL); + header.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + header.setLayout(new GridLayout(2, false)); + + // Text Area to filter + filterTxt = new Text(header, SWT.BORDER | SWT.SINGLE); + filterTxt.setMessage(FILTER_HELP_MSG); + GridData gd = new GridData(SWT.FILL, SWT.FILL, false, false); + gd.grabExcessHorizontalSpace = true; + filterTxt.setLayoutData(gd); + filterTxt.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent event) { + refreshFilteredList(); + } + }); + + Button resetBtn = new Button(header, SWT.PUSH); + resetBtn.setImage(FILTER_RESET); + resetBtn.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + resetFilter(); + } + public void widgetDefaultSelected(SelectionEvent e) { } + }); + + } + + private void resetFilter() { + filterTxt.setText(""); + filterTxt.setMessage(FILTER_HELP_MSG); + } + + private void refreshFilteredList() { + List nodes; + try { + nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session, + filterTxt.getText())); + viewer.setInput(nodes.toArray()); + } catch (RepositoryException e) { + throw new ArgeoException("Unable to list users", e); } } -} + /** Build repository request */ + private NodeIterator listFilteredElements(Session session, String filter) + throws RepositoryException { + QueryManager queryManager = session.getWorkspace().getQueryManager(); + QueryObjectModelFactory factory = queryManager.getQOMFactory(); + + final String bundleArtifactsSelector = "userProfiles"; + Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE, + bundleArtifactsSelector); + + // Create a dynamic operand for each property on which we want to filter + DynamicOperand userIdDO = factory.propertyValue( + source.getSelectorName(), ARGEO_USER_ID); + DynamicOperand fullNameDO = factory.propertyValue( + source.getSelectorName(), Property.JCR_TITLE); + DynamicOperand mailDO = factory.propertyValue(source.getSelectorName(), + ARGEO_PRIMARY_EMAIL); + + // Default Constraint: no source artifacts + Constraint defaultC = null; + + // Build constraints based the textArea content + if (filter != null && !"".equals(filter.trim())) { + // Parse the String + String[] strs = filter.trim().split(" "); + for (String token : strs) { + token = token.replace('*', '%'); + StaticOperand so = factory.literal(session.getValueFactory() + .createValue("%" + token + "%")); + + Constraint currC = factory.comparison(userIdDO, + QueryObjectModelFactory.JCR_OPERATOR_LIKE, so); + currC = factory.or(currC, factory.comparison(fullNameDO, + QueryObjectModelFactory.JCR_OPERATOR_LIKE, so)); + currC = factory.or(currC, factory.comparison(mailDO, + QueryObjectModelFactory.JCR_OPERATOR_LIKE, so)); + + if (defaultC == null) + defaultC = currC; + else + defaultC = factory.and(defaultC, currC); + } + } + + Ordering order = factory.descending(factory.propertyValue( + bundleArtifactsSelector, ARGEO_USER_ID)); + // Ordering order2 = factory.ascending(factory.propertyValue( + // bundleArtifactsSelector, ARGEO_PRIMARY_EMAIL)); + // Ordering[] orderings = { order, order2 }; + Ordering[] orderings = { order }; + + QueryObjectModel query = factory.createQuery(source, defaultC, + orderings, null); + + QueryResult result = query.execute(); + return result.getNodes(); + } +} \ No newline at end of file