From 4390bdf66e304558ecf692fdfb3983b7da4bc5ac Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Mon, 23 Nov 2020 19:22:16 +0100 Subject: [PATCH] Suite user administration. --- .../src/org/argeo/entity/EntityType.java | 2 +- .../src/org/argeo/entity/entity.cnd | 4 + org.argeo.suite.ui/OSGI-INF/cmsApp.xml | 1 + .../org/argeo/suite/ui/AdminEntryArea.java | 156 +++++++++++++++++- .../src/org/argeo/suite/ui/SuiteApp.java | 29 ++++ .../src/org/argeo/suite/ui/SuiteEvent.java | 8 + .../src/org/argeo/suite/ui/SuiteUi.java | 9 +- .../argeo/suite/ui/SuiteUserUiProvider.java | 51 +++++- 8 files changed, 251 insertions(+), 9 deletions(-) diff --git a/org.argeo.entity.api/src/org/argeo/entity/EntityType.java b/org.argeo.entity.api/src/org/argeo/entity/EntityType.java index 822bbd9..408b142 100644 --- a/org.argeo.entity.api/src/org/argeo/entity/EntityType.java +++ b/org.argeo.entity.api/src/org/argeo/entity/EntityType.java @@ -11,7 +11,7 @@ public enum EntityType implements JcrName { // graphics box, // ldap - person; + person, user; @Override public String getPrefix() { diff --git a/org.argeo.entity.api/src/org/argeo/entity/entity.cnd b/org.argeo.entity.api/src/org/argeo/entity/entity.cnd index 8a6b2e0..85da650 100644 --- a/org.argeo.entity.api/src/org/argeo/entity/entity.cnd +++ b/org.argeo.entity.api/src/org/argeo/entity/entity.cnd @@ -74,3 +74,7 @@ mixin mixin - ldap:sn (String) - ldap:givenName (String) + +[entity:user] > entity:person +- ldap:uid (String) + diff --git a/org.argeo.suite.ui/OSGI-INF/cmsApp.xml b/org.argeo.suite.ui/OSGI-INF/cmsApp.xml index 6818fb8..e42eeeb 100644 --- a/org.argeo.suite.ui/OSGI-INF/cmsApp.xml +++ b/org.argeo.suite.ui/OSGI-INF/cmsApp.xml @@ -10,4 +10,5 @@ + diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java index fd390f5..0e7d2d8 100644 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java +++ b/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java @@ -1,18 +1,170 @@ package org.argeo.suite.ui; +import java.util.Set; + import javax.jcr.Node; import javax.jcr.RepositoryException; +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.ui.CmsTheme; import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.entity.EntityType; +import org.argeo.jcr.Jcr; +import org.argeo.jcr.JcrUtils; +import org.argeo.naming.LdapAttrs; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.osgi.service.useradmin.User; +/** Entry to the admin area. */ public class AdminEntryArea implements CmsUiProvider { + private CmsUserManager cmsUserManager; + @Override public Control createUi(Composite parent, Node context) throws RepositoryException { - // TODO Auto-generated method stub - return null; + CmsTheme theme = CmsTheme.getCmsTheme(parent); + parent.setLayout(new GridLayout()); + TableViewer usersViewer = new TableViewer(parent); + usersViewer.setContentProvider(new UsersContentProvider()); + + TableViewerColumn idCol = new TableViewerColumn(usersViewer, SWT.NONE); + idCol.getColumn().setWidth(70); + idCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.uid.name()); + } + }); + + TableViewerColumn givenNameCol = new TableViewerColumn(usersViewer, SWT.NONE); + givenNameCol.getColumn().setWidth(70); + givenNameCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.givenName.name()); + } + }); + + TableViewerColumn snCol = new TableViewerColumn(usersViewer, SWT.NONE); + snCol.getColumn().setWidth(70); + snCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.sn.name()); + } + }); + + TableViewerColumn mailCol = new TableViewerColumn(usersViewer, SWT.NONE); + mailCol.getColumn().setWidth(200); + mailCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.mail.name()); + } + }); + + Composite bottom = new Composite(parent, SWT.NONE); + bottom.setLayoutData(CmsUiUtils.fillWidth()); + bottom.setLayout(CmsUiUtils.noSpaceGridLayout()); + ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); + bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); + ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); + deleteItem.setEnabled(false); +// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); + deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); + ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); + addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); + usersViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + User user = (User) usersViewer.getStructuredSelection().getFirstElement(); + if (user != null) { + Node userNode = getOrCreateUserNode(user, context); + CmsView.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), + SuiteEvent.eventProperties(userNode)); + } + + } + }); + usersViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + User user = (User) usersViewer.getStructuredSelection().getFirstElement(); + if (user != null) { + Node userNode = getOrCreateUserNode(user, context); + CmsView.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), + SuiteEvent.eventProperties(userNode)); + deleteItem.setEnabled(true); + } else { + deleteItem.setEnabled(false); + } + } + }); + + usersViewer.getTable().setLayoutData(CmsUiUtils.fillAll()); + usersViewer.setInput(cmsUserManager); + + return usersViewer.getTable(); + } + + private Node getOrCreateUserNode(User user, Node context) { + return JcrUtils.mkdirs(Jcr.getSession(context), + "/" + EntityType.user.name() + "/" + getUserProperty(user, LdapAttrs.uid.name()), + EntityType.user.get()); + } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; + } + + class UsersContentProvider implements IStructuredContentProvider { + + @Override + public Object[] getElements(Object inputElement) { + CmsUserManager cum = (CmsUserManager) inputElement; + String baseGroup = "cn=apaf-coworker,cn=groups,cn=accounts,dc=id,dc=argeo,dc=pro"; + Set users = cum.listUsersInGroup(baseGroup, null); + return users.toArray(); + } + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; } } diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java index ecb9ff7..62e1a70 100644 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java +++ b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java @@ -18,10 +18,12 @@ import javax.jcr.nodetype.NodeType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.api.NodeUtils; +import org.argeo.cms.CmsUserManager; import org.argeo.cms.ui.AbstractCmsApp; import org.argeo.cms.ui.CmsTheme; import org.argeo.cms.ui.CmsUiProvider; import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.MvcProvider; import org.argeo.cms.ui.dialogs.CmsFeedback; import org.argeo.cms.ui.util.CmsEvent; import org.argeo.cms.ui.util.CmsUiUtils; @@ -54,9 +56,13 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { private final static String DEFAULT_THEME_ID = "org.argeo.suite.theme.default"; private Map> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>()); +// private Map>> mvcProvidersByPid = Collections +// .synchronizedMap(new HashMap<>()); private Map> uiProvidersByType = Collections.synchronizedMap(new HashMap<>()); private Map> layers = Collections.synchronizedSortedMap(new TreeMap<>()); + private CmsUserManager cmsUserManager; + // TODO make more optimal or via CmsSession/CmsView private Map managedUis = new HashMap<>(); @@ -327,6 +333,25 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { } +// public void addMvcProvider(MvcProvider uiProvider, Map properties) { +// if (properties.containsKey(Constants.SERVICE_PID)) { +// String pid = (String) properties.get(Constants.SERVICE_PID); +// RankedObject.putIfHigherRank(mvcProvidersByPid, pid, uiProvider, properties); +// } +// } +// +// public void removeMvcProvider(MvcProvider uiProvider, Map properties) { +// if (properties.containsKey(Constants.SERVICE_PID)) { +// String pid = (String) properties.get(Constants.SERVICE_PID); +// if (mvcProvidersByPid.containsKey(pid)) { +// if (mvcProvidersByPid.get(pid).equals(new RankedObject>(uiProvider, properties))) { +// mvcProvidersByPid.remove(pid); +// } +// } +// } +// +// } + public void addLayer(SuiteLayer layer, Map properties) { if (properties.containsKey(Constants.SERVICE_PID)) { String pid = (String) properties.get(Constants.SERVICE_PID); @@ -345,6 +370,10 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { } } + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + @Override public void handleEvent(Event event) { diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java index 99e4988..a77dc7a 100644 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java +++ b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java @@ -7,6 +7,7 @@ import javax.jcr.Node; import org.argeo.cms.ui.util.CmsEvent; import org.argeo.jcr.Jcr; +import org.osgi.service.useradmin.User; /** Events specific to Argeo Suite. */ public enum SuiteEvent implements CmsEvent { @@ -14,6 +15,7 @@ public enum SuiteEvent implements CmsEvent { public final static String LAYER = "layer"; public final static String NODE_ID = "nodeId"; + public final static String USERNAME = "username"; public final static String WORKSPACE = "workspace"; public String getTopicBase() { @@ -26,4 +28,10 @@ public enum SuiteEvent implements CmsEvent { properties.put(WORKSPACE, Jcr.getWorkspaceName(node)); return properties; } + + public static Map eventProperties(User user) { + Map properties = new HashMap<>(); + properties.put(USERNAME, user.getName()); + return properties; + } } diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java index 8320f76..3d1e938 100644 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java +++ b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java @@ -106,10 +106,11 @@ class SuiteUi extends Composite { context = userHome; } Composite toShow = getLayer(layer, context); - getDisplay().syncExec(() -> { - toShow.moveAbove(null); - dynamicArea.layout(true, true); - }); + if (!isDisposed()) + getDisplay().syncExec(() -> { + toShow.moveAbove(null); + dynamicArea.layout(true, true); + }); currentLayerId = layer; return toShow; } diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java index 4ec1bfc..0a35161 100644 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java +++ b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java @@ -3,16 +3,63 @@ package org.argeo.suite.ui; import javax.jcr.Node; import javax.jcr.RepositoryException; +import org.argeo.cms.CmsUserManager; import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.ui.viewers.Section; +import org.argeo.naming.LdapAttrs; +import org.eclipse.swt.SWT; 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.osgi.service.useradmin.User; +/** Edit a suite user. */ public class SuiteUserUiProvider implements CmsUiProvider { + private CmsUserManager cmsUserManager; @Override public Control createUi(Composite parent, Node context) throws RepositoryException { - // TODO Auto-generated method stub - return null; + Section main = new Section(parent, SWT.NONE, context); + main.setLayoutData(CmsUiUtils.fillAll()); + + String uid = context.getName(); + User user = cmsUserManager.getUserFromLocalId(uid); + + Text givenName = new Text(main, SWT.SINGLE); + givenName.setText(getUserProperty(user, LdapAttrs.givenName.name())); + + Text sn = new Text(main, SWT.SINGLE); + sn.setText(getUserProperty(user, LdapAttrs.sn.name())); + + Text email = new Text(main, SWT.SINGLE); + email.setText(getUserProperty(user, LdapAttrs.mail.name())); + + Label lbl = new Label(main, SWT.NONE); + lbl.setText(uid); + + Label dnL = new Label(main, SWT.NONE); + dnL.setText(user.getName()); + + // roles + Section rolesSection = new Section(main, SWT.NONE, context); + new Label(rolesSection, SWT.NONE).setText("Roles:"); + String[] roles = cmsUserManager.getUserRoles(user.getName()); + for (String role : roles) { + new Label(rolesSection, SWT.NONE).setText(role); + } + + return lbl; + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; } } -- 2.30.2