Create new user as a POSIX account
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 21 Sep 2022 05:52:25 +0000 (07:52 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 21 Sep 2022 05:52:25 +0000 (07:52 +0200)
13 files changed:
org.argeo.app.api/src/org/argeo/app/api/IdRange.java [new file with mode: 0644]
org.argeo.app.core/src/org/argeo/app/core/SuiteUtils.java
org.argeo.app.ui/OSGI-INF/l10n/bundle.properties
org.argeo.app.ui/OSGI-INF/l10n/bundle_fr.properties
org.argeo.app.ui/OSGI-INF/peopleLayer.xml
org.argeo.app.ui/src/org/argeo/app/ui/DefaultEditionLayer.java
org.argeo.app.ui/src/org/argeo/app/ui/SuiteApp.java
org.argeo.app.ui/src/org/argeo/app/ui/SuiteLayer.java
org.argeo.app.ui/src/org/argeo/app/ui/SuiteMsg.java
org.argeo.app.ui/src/org/argeo/app/ui/SuiteUi.java
org.argeo.app.ui/src/org/argeo/app/ui/dialogs/NewUserWizard.java [deleted file]
org.argeo.app.ui/src/org/argeo/app/ui/people/NewUserForm.java [new file with mode: 0644]
org.argeo.app.ui/src/org/argeo/app/ui/people/PeopleEntryArea.java

diff --git a/org.argeo.app.api/src/org/argeo/app/api/IdRange.java b/org.argeo.app.api/src/org/argeo/app/api/IdRange.java
new file mode 100644 (file)
index 0000000..d96c789
--- /dev/null
@@ -0,0 +1,60 @@
+package org.argeo.app.api;
+
+/** A range of numerical IDs (typically numerical uid or gid). */
+public class IdRange {
+
+       private final long min;
+       private final long max;
+
+       public IdRange(long min, long max) {
+               this.min = min;
+               this.max = max;
+       }
+
+       public IdRange(long minPow10) {
+               this(minPow10, maxFromMinPow10(minPow10));
+       }
+
+       public long getMin() {
+               return min;
+       }
+
+       public long getMax() {
+               return max;
+       }
+
+       private static long maxFromMinPow10(long minPow10) {
+               if ((minPow10 % 100) != 0) {
+                       throw new IllegalArgumentException(minPow10 + " must at least ends with two zeroes");
+               }
+               int exp = 2;
+               exp: for (int i = exp + 1; i < 10; i++) {
+                       if ((minPow10 % pow10(i)) != 0)
+                               break exp;
+                       exp++;
+               }
+               System.out.println(exp);
+
+               long max = minPow10 + pow10(exp) - 1;
+               return max;
+       }
+
+       /** Power of 10. */
+       private static long pow10(int exp) {
+               if (exp == 0)
+                       return 1;
+               else
+                       return 10 * pow10(exp - 1);
+       }
+
+       public static void main(String... args) {
+               System.out.println(maxFromMinPow10(100));
+               System.out.println(maxFromMinPow10(78500));
+               System.out.println(maxFromMinPow10(716850000));
+
+//             System.out.println(pow10(6));
+//             System.out.println(maxFromMinPow10(12));
+//             System.out.println(maxFromMinPow10(124));
+//             System.out.println(maxFromMinPow10(99814565));
+       }
+}
index 6b63cdb4d30115e21db16267eb1afd2c5b191cbe..531d3a35c050ab6408cf8533f9a5c47f9493be2b 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.app.core;
 
 import java.util.HashSet;
+import java.util.Optional;
 import java.util.Set;
 
 import javax.jcr.Node;
@@ -9,7 +10,9 @@ import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.security.Privilege;
 import javax.security.auth.x500.X500Principal;
+import javax.xml.namespace.QName;
 
+import org.argeo.api.acr.Content;
 import org.argeo.api.cms.CmsConstants;
 import org.argeo.api.cms.CmsSession;
 import org.argeo.app.api.EntityType;
@@ -17,6 +20,7 @@ import org.argeo.cms.auth.RoleNameUtils;
 import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.util.naming.LdapAttrs;
+import org.argeo.util.naming.LdapObjs;
 
 /** Utilities around the Argeo Suite APIs. */
 public class SuiteUtils {
@@ -96,11 +100,6 @@ public class SuiteUtils {
                }
        }
 
-       /** Singleton. */
-       private SuiteUtils() {
-
-       }
-
        public static Set<String> extractRoles(String[] semiColArr) {
                Set<String> res = new HashSet<>();
                // TODO factorize and make it more robust
@@ -121,4 +120,33 @@ public class SuiteUtils {
                return res;
        }
 
+       synchronized static public long findNextId(Content hierarchyUnit, QName cclass) {
+               if (!hierarchyUnit.hasContentClass(LdapObjs.posixGroup.qName())) 
+                       throw new IllegalArgumentException(hierarchyUnit + " is not a POSIX group");
+               
+               long min = hierarchyUnit.get(LdapAttrs.gidNumber.qName(), Long.class).orElseThrow();
+               long currentMax = 0l;
+               for (Content childHu : hierarchyUnit) {
+                       if (!childHu.hasContentClass(LdapObjs.organizationalUnit.qName()))
+                               continue;
+                       // FIXME filter out functional hierarchy unit
+                       for (Content role : childHu) {
+                               if (role.hasContentClass(cclass)) {
+
+                                       if (LdapObjs.posixAccount.qName().equals(cclass)) {
+                                               Long id = role.get(LdapAttrs.uidNumber.qName(), Long.class).orElseThrow();
+                                               if (id > currentMax)
+                                                       currentMax = id;
+                                       }
+                               }
+                       }
+               }
+               if (currentMax == 0l)
+                       return min;
+               return currentMax + 1;
+       }
+
+       /** Singleton. */
+       private SuiteUtils() {
+       }
 }
index 8b76a475b4bd470393e3204298d2f70dd6cf0400..0dd3532e93ce23d53ea706235949a2591446425b 100644 (file)
@@ -106,3 +106,6 @@ content=content
 # Geo
 map=map
 
+# Feedback messages
+allFieldsMustBeSet=All fields must be set
+
index 225e5fdf9f6a3957d866e0402241c9315d02f826..3a9ad4d2f99c2e6872e780b71f227d7340b49e7e 100644 (file)
@@ -100,3 +100,6 @@ pickUp=Choisir
 # Tags
 confirmNewTag=Le tag #{0} n'existe pas encore. Voulez-vous le créer?
 cannotCreateTag=Le tag #{0} n'existe pas encore et vous n'avez pas les droits pour le créer.
+
+# Feedback messages
+allFieldsMustBeSet=Toutes les données doivent être renseignées
index 159da121bcaced322d26c202469fa1c7a04d4d17..4715f1c5d4e3c97c7aa264d8b31b0e0e684de478 100644 (file)
@@ -5,5 +5,5 @@
    <service>
       <provide interface="org.argeo.app.ui.SuiteLayer"/>
    </service>
-   <reference bind="setEntryArea" cardinality="1..1" interface="org.argeo.cms.ui.CmsUiProvider" name="CmsUiProvider" policy="dynamic" target="(service.pid=argeo.people.ui.peopleEntryArea)"/>
+   <reference bind="setEntryArea" cardinality="1..1" interface="org.argeo.cms.swt.acr.SwtUiProvider" name="CmsUiProvider" policy="dynamic" target="(service.pid=argeo.people.ui.peopleEntryArea)"/>
 </scr:component>
index 97bede26da8083c06af9f50c550527c1836504fb..9e399f0e8d6eeaba335b72c60f4058809c935b5a 100644 (file)
@@ -17,10 +17,12 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 import org.osgi.framework.wiring.BundleWiring;
 
 /** An app layer based on an entry area and an editor area. */
 public class DefaultEditionLayer implements SuiteLayer {
+       private String id;
        private SwtUiProvider entryArea;
        private SwtUiProvider defaultView;
        private SwtUiProvider workArea;
@@ -117,7 +119,15 @@ public class DefaultEditionLayer implements SuiteLayer {
                return title;
        }
 
+       @Override
+       public String getId() {
+               return id;
+       }
+
        public void init(BundleContext bundleContext, Map<String, Object> properties) {
+               String pid = (String) properties.get(Constants.SERVICE_PID);
+               id = pid;
+
                weights = LangUtils.toStringList(properties.get(Property.weights.name()));
                startMaximized = properties.containsKey(Property.startMaximized.name())
                                && "true".equals(properties.get(Property.startMaximized.name()));
index 9ad2673fc1216d79746a5de580c2a6b7f56dc359..ef4aaff9545953eb3530bf09f52a964f00c22f81 100644 (file)
@@ -2,7 +2,6 @@ package org.argeo.app.ui;
 
 import static org.argeo.api.cms.ux.CmsView.CMS_VIEW_UID_PROPERTY;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -659,27 +658,39 @@ public class SuiteApp extends AbstractCmsApp implements CmsEventSubscriber {
                }
        }
 
+//     public void addLayer(SuiteLayer layer, Map<String, Object> properties) {
+//             if (!properties.containsKey(Constants.SERVICE_PID))
+//                     throw new IllegalArgumentException("A layer must have an ID");
+//             String pid = (String) properties.get(Constants.SERVICE_PID);
+//             List<String> types = properties.containsKey(EntityConstants.TYPE)
+//                             ? LangUtils.toStringList(properties.get(EntityConstants.TYPE))
+//                             : new ArrayList<>();
+//             if (types.isEmpty()) {
+//                     RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
+//             } else {
+//                     if (layersByPid.containsKey(pid)) {
+//                             RankedObject<SuiteLayer> current = layersByPid.get(pid);
+//                             List<String> currentTypes = current.getProperties().containsKey(EntityConstants.TYPE)
+//                                             ? LangUtils.toStringList(current.getProperties().get(EntityConstants.TYPE))
+//                                             : new ArrayList<>();
+//                             if (!types.containsAll(currentTypes)) {
+//                                     throw new IllegalArgumentException("Higher-ranked layer " + pid + " contains only types " + types
+//                                                     + ", while it must override all " + currentTypes);
+//                             }
+//                     }
+//                     RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
+//                     for (String type : types)
+//                             RankedObject.putIfHigherRank(layersByType, type, layer, properties);
+//             }
+//     }
+
        public void addLayer(SuiteLayer layer, Map<String, Object> properties) {
-               if (!properties.containsKey(Constants.SERVICE_PID))
-                       throw new IllegalArgumentException("A layer must have an ID");
-               String pid = (String) properties.get(Constants.SERVICE_PID);
-               List<String> types = properties.containsKey(EntityConstants.TYPE)
-                               ? LangUtils.toStringList(properties.get(EntityConstants.TYPE))
-                               : new ArrayList<>();
-               if (types.isEmpty()) {
-                       RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
-               } else {
-                       if (layersByPid.containsKey(pid)) {
-                               RankedObject<SuiteLayer> current = layersByPid.get(pid);
-                               List<String> currentTypes = current.getProperties().containsKey(EntityConstants.TYPE)
-                                               ? LangUtils.toStringList(current.getProperties().get(EntityConstants.TYPE))
-                                               : new ArrayList<>();
-                               if (!types.containsAll(currentTypes)) {
-                                       throw new IllegalArgumentException("Higher-ranked layer " + pid + " contains only types " + types
-                                                       + ", while it must override all " + currentTypes);
-                               }
-                       }
+               if (properties.containsKey(Constants.SERVICE_PID)) {
+                       String pid = (String) properties.get(Constants.SERVICE_PID);
                        RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
+               }
+               if (properties.containsKey(EntityConstants.TYPE)) {
+                       List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
                        for (String type : types)
                                RankedObject.putIfHigherRank(layersByType, type, layer, properties);
                }
index 161856360f44fb9b6953420b2ed4251666dbc96d..b97230dc0e1c76438352bf55f14943de5b5ab2d6 100644 (file)
@@ -11,8 +11,10 @@ public interface SuiteLayer extends SwtUiProvider {
                title, icon, weights, startMaximized, singleTab, fixedEntryArea;
        }
 
+       String getId();
+
        void view(SwtUiProvider uiProvider, Composite workArea, Content context);
-       
+
        Content getCurrentContext(Composite workArea);
 
        default void open(SwtUiProvider uiProvider, Composite workArea, Content context) {
index fae15dfd22393748384e6f9f8c9e6ffe5d1c71e3..1162144fce7a66e4dd130ae3c271592a6100ee87 100644 (file)
@@ -30,5 +30,9 @@ public enum SuiteMsg implements Localized {
        // Generic
        label, aCustomLabel, description, value, name, primary, add, save, pickup,
        // Tag
-       confirmNewTag, cannotCreateTag;
+       confirmNewTag, cannotCreateTag,
+       // Feddback messages
+       allFieldsMustBeSet,
+       //
+       ;
 }
index 2e27d6a439854b9ab06bbab40156fdd0de1bf289..de060df0b086563f90d5653039bc8fe35b726c42 100644 (file)
@@ -144,8 +144,9 @@ class SuiteUi extends Composite implements CmsUi {
                // TODO make it more robust
                for (String layerId : layers.keySet()) {
                        SuiteLayer l = layers.get(layerId);
-                       if (layer == l) {
+                       if (layer.getId().equals(l.getId())) {
                                switchToLayer(layerId, context);
+                               return;
                        }
                }
                throw new IllegalArgumentException("Layer is not registered.");
diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/dialogs/NewUserWizard.java b/org.argeo.app.ui/src/org/argeo/app/ui/dialogs/NewUserWizard.java
deleted file mode 100644 (file)
index 5c7a6d2..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.argeo.app.ui.dialogs;
-
-import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty;
-
-import org.argeo.app.ui.SuiteMsg;
-import org.argeo.app.ui.SuiteUiUtils;
-import org.argeo.cms.swt.dialogs.CmsFeedback;
-import org.argeo.cms.swt.widgets.SwtGuidedFormPage;
-import org.argeo.cms.ux.widgets.AbstractGuidedForm;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.util.directory.HierarchyUnit;
-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.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Text;
-
-/** Ask first & last name. Update the passed node on finish */
-public class NewUserWizard extends AbstractGuidedForm {
-       // private final static Log log = LogFactory.getLog(NewPersonWizard.class);
-
-       // Context
-//     private Node person;
-       private HierarchyUnit hierarchyUnit;
-       // This page widgets
-       protected Text lastNameTxt;
-       protected Text firstNameTxt;
-       // private Button useDistinctDisplayNameBtn;
-       // private Text displayNameTxt;
-
-       public NewUserWizard(HierarchyUnit hierarchyUnit) {
-               this.hierarchyUnit = hierarchyUnit;
-       }
-
-       @Override
-       public void addPages() {
-               try {
-                       MainInfoPage page = new MainInfoPage("Main page");
-                       addPage(page);
-               } catch (Exception e) {
-                       throw new RuntimeException("Cannot add page to wizard", e);
-               }
-               setFormTitle(SuiteMsg.personWizardWindowTitle.lead());
-       }
-
-       /**
-        * Called when the user click on 'Finish' in the wizard. The task is then
-        * created and the corresponding session saved.
-        */
-       @Override
-       public boolean performFinish() {
-               String lastName = lastNameTxt.getText();
-               String firstName = firstNameTxt.getText();
-               // String displayName = displayNameTxt.getText();
-               // boolean useDistinct = useDistinctDisplayNameBtn.getSelection();
-               if (EclipseUiUtils.isEmpty(lastName) && EclipseUiUtils.isEmpty(firstName)) {
-//                     MessageDialog.openError(getShell(), "Non-valid information",
-//                                     "Please enter at least a name that is not empty.");
-                       CmsFeedback.show("Please enter at least a name that is not empty.");
-                       return false;
-               } else {
-//                     ConnectJcrUtils.setJcrProperty(person, PEOPLE_LAST_NAME, PropertyType.STRING, lastName);
-//                     ConnectJcrUtils.setJcrProperty(person, PEOPLE_FIRST_NAME, PropertyType.STRING, firstName);
-//                     String fullName = firstName + " " + lastName;
-//                     ConnectJcrUtils.setJcrProperty(person, PEOPLE_DISPLAY_NAME, PropertyType.STRING, fullName);
-                       return true;
-               }
-       }
-
-       @Override
-       public boolean performCancel() {
-               return true;
-       }
-
-       @Override
-       public boolean canFinish() {
-               String lastName = lastNameTxt.getText();
-               String firstName = firstNameTxt.getText();
-               if (isEmpty(lastName) && isEmpty(firstName)) {
-                       return false;
-               } else
-                       return true;
-       }
-
-       protected class MainInfoPage extends SwtGuidedFormPage {
-
-               public MainInfoPage(String pageName) {
-                       super(pageName);
-                       setTitle(SuiteMsg.personWizardPageTitle.lead());
-                       // setMessage("Please enter a last name and/or a first name.");
-               }
-
-               public void createControl(Composite parent) {
-                       parent.setLayout(new GridLayout(2, false));
-
-                       // FirstName
-                       SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName);
-                       firstNameTxt = new Text(parent, SWT.BORDER);
-                       // firstNameTxt.setMessage("a first name");
-                       firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
-
-                       // LastName
-                       SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName);
-                       lastNameTxt = new Text(parent, SWT.BORDER);
-                       // lastNameTxt.setMessage("a last name");
-                       lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
-
-                       // Display Name
-                       // useDistinctDisplayNameBtn = new Button(parent, SWT.CHECK);
-                       // useDistinctDisplayNameBtn.setText("Define a disting display name");
-                       // useDistinctDisplayNameBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER,
-                       // true, false, 2, 1));
-                       //
-                       // ConnectWorkbenchUtils.createBoldLabel(parent, "Display Name");
-                       // displayNameTxt = new Text(parent, SWT.BORDER);
-                       // displayNameTxt.setMessage("an optional display name");
-                       // displayNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
-                       // false));
-                       // displayNameTxt.setEnabled(false);
-                       //
-                       // useDistinctDisplayNameBtn.addSelectionListener(new SelectionAdapter() {
-                       // private static final long serialVersionUID = 1L;
-                       //
-                       // @Override
-                       // public void widgetSelected(SelectionEvent e) {
-                       // displayNameTxt.setEnabled(useDistinctDisplayNameBtn.getSelection());
-                       // }
-                       // });
-
-                       ModifyListener ml = new ModifyListener() {
-                               private static final long serialVersionUID = -1628130380128946886L;
-
-                               @Override
-                               public void modifyText(ModifyEvent event) {
-                                       getView().updateButtons();
-                               }
-                       };
-
-                       firstNameTxt.addModifyListener(ml);
-                       lastNameTxt.addModifyListener(ml);
-                       // displayNameTxt.addModifyListener(ml);
-
-                       // Don't forget this.
-                       // setControl(firstNameTxt);
-                       firstNameTxt.setFocus();
-               }
-       }
-}
diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/people/NewUserForm.java b/org.argeo.app.ui/src/org/argeo/app/ui/people/NewUserForm.java
new file mode 100644 (file)
index 0000000..ed9c4f4
--- /dev/null
@@ -0,0 +1,162 @@
+package org.argeo.app.ui.people;
+
+import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.argeo.api.acr.Content;
+import org.argeo.app.core.SuiteUtils;
+import org.argeo.app.ui.SuiteMsg;
+import org.argeo.app.ui.SuiteUiUtils;
+import org.argeo.cms.CmsUserManager;
+import org.argeo.cms.acr.ContentUtils;
+import org.argeo.cms.swt.dialogs.CmsFeedback;
+import org.argeo.cms.swt.widgets.SwtGuidedFormPage;
+import org.argeo.cms.ux.widgets.AbstractGuidedForm;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.util.directory.HierarchyUnit;
+import org.argeo.util.naming.LdapAttrs;
+import org.argeo.util.naming.LdapObjs;
+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.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.osgi.service.useradmin.User;
+
+/** Ask first & last name. Update the passed node on finish */
+public class NewUserForm extends AbstractGuidedForm {
+       private Content hierarchyUnit;
+       private CmsUserManager cmsUserManager;
+
+       protected Text lastNameT;
+       protected Text firstNameT;
+       protected Text emailT;
+
+       public NewUserForm(CmsUserManager cmsUserManager, Content hierarchyUnit) {
+               this.hierarchyUnit = hierarchyUnit;
+               if (!hierarchyUnit.hasContentClass(LdapObjs.posixGroup.qName()))
+                       throw new IllegalArgumentException(hierarchyUnit + " is not a POSIX group");
+               this.cmsUserManager = cmsUserManager;
+       }
+
+       @Override
+       public void addPages() {
+               try {
+                       MainInfoPage page = new MainInfoPage("Main page");
+                       addPage(page);
+               } catch (Exception e) {
+                       throw new RuntimeException("Cannot add page to wizard", e);
+               }
+               setFormTitle(SuiteMsg.personWizardWindowTitle.lead());
+       }
+
+       /**
+        * Called when the user click on 'Finish' in the wizard. The task is then
+        * created and the corresponding session saved.
+        */
+       @Override
+       public boolean performFinish() {
+               String lastName = lastNameT.getText();
+               String firstName = firstNameT.getText();
+               String email = emailT.getText();
+               if (EclipseUiUtils.isEmpty(lastName) || EclipseUiUtils.isEmpty(firstName) || EclipseUiUtils.isEmpty(email)) {
+                       CmsFeedback.show(SuiteMsg.allFieldsMustBeSet.lead());
+                       return false;
+               } else {
+                       UUID uuid = UUID.randomUUID();
+                       String shortId = uuid.toString().split("-")[0];
+                       String uid = "u" + shortId;
+                       HierarchyUnit hu = hierarchyUnit.adapt(HierarchyUnit.class);
+                       String username = "uid=" + uid + ",ou=People," + hu.getBase();
+
+                       Map<String, Object> properties = new HashMap<>();
+                       properties.put(LdapAttrs.givenName.name(), firstName);
+                       properties.put(LdapAttrs.sn.name(), lastName);
+                       properties.put(LdapAttrs.mail.name(), email);
+                       properties.put(LdapAttrs.cn.name(), firstName + " " + lastName);
+                       properties.put(LdapAttrs.employeeNumber.name(), uuid.toString());
+
+                       Map<String, Object> credentials = new HashMap<>();
+                       User user = cmsUserManager.createUser(username, properties, credentials);
+
+                       Long huGidNumber = hierarchyUnit.get(LdapAttrs.gidNumber.qName(), Long.class).orElseThrow();
+                       Long nextUserId = SuiteUtils.findNextId(hierarchyUnit, LdapObjs.posixAccount.qName());
+                       String homeDirectory = "/home/" + uid;
+                       Map<String, Object> additionalProperties = new HashMap<>();
+                       additionalProperties.put(LdapAttrs.uidNumber.name(), nextUserId.toString());
+                       additionalProperties.put(LdapAttrs.gidNumber.name(), huGidNumber.toString());
+                       additionalProperties.put(LdapAttrs.homeDirectory.name(), homeDirectory);
+
+                       Set<String> objectClasses = new HashSet<>();
+                       objectClasses.add(LdapObjs.posixAccount.name());
+                       cmsUserManager.addObjectClasses(user, objectClasses, additionalProperties);
+                       return true;
+               }
+       }
+
+       @Override
+       public boolean performCancel() {
+               return true;
+       }
+
+       @Override
+       public boolean canFinish() {
+               String lastName = lastNameT.getText();
+               String firstName = firstNameT.getText();
+               String email = emailT.getText();
+               if (isEmpty(lastName) || isEmpty(firstName) || isEmpty(email)) {
+                       return false;
+               } else
+                       return true;
+       }
+
+       protected class MainInfoPage extends SwtGuidedFormPage {
+
+               public MainInfoPage(String pageName) {
+                       super(pageName);
+                       setTitle(SuiteMsg.personWizardPageTitle.lead());
+               }
+
+               public void createControl(Composite parent) {
+                       parent.setLayout(new GridLayout(2, false));
+
+                       // FirstName
+                       SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName);
+                       firstNameT = new Text(parent, SWT.BORDER);
+                       // firstNameTxt.setMessage("a first name");
+                       firstNameT.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+                       // LastName
+                       SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName);
+                       lastNameT = new Text(parent, SWT.BORDER);
+                       // lastNameTxt.setMessage("a last name");
+                       lastNameT.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+                       SuiteUiUtils.createBoldLabel(parent, SuiteMsg.email);
+                       emailT = new Text(parent, SWT.BORDER);
+                       emailT.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+                       ModifyListener ml = new ModifyListener() {
+                               private static final long serialVersionUID = 1939491923843870844L;
+
+                               @Override
+                               public void modifyText(ModifyEvent event) {
+                                       getView().updateButtons();
+                               }
+                       };
+
+                       firstNameT.addModifyListener(ml);
+                       lastNameT.addModifyListener(ml);
+                       emailT.addModifyListener(ml);
+
+                       firstNameT.setFocus();
+               }
+       }
+}
index 8ee656a6ffebe0bdff5842da25cd5d19e1c50f91..4a92c20630456bb42094ece6d36a9e40611d5033 100644 (file)
@@ -13,14 +13,12 @@ import org.argeo.api.cms.ux.CmsIcon;
 import org.argeo.api.cms.ux.CmsView;
 import org.argeo.app.ui.SuiteEvent;
 import org.argeo.app.ui.SuiteIcon;
-import org.argeo.app.ui.dialogs.NewUserWizard;
 import org.argeo.cms.CmsUserManager;
 import org.argeo.cms.acr.ContentUtils;
 import org.argeo.cms.auth.CmsRole;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.UserAdminUtils;
 import org.argeo.cms.jcr.acr.JcrContent;
-import org.argeo.cms.jface.dialog.CmsWizardDialog;
 import org.argeo.cms.swt.CmsSwtTheme;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.swt.Selected;
@@ -40,7 +38,6 @@ import org.argeo.util.directory.ldap.IpaUtils;
 import org.argeo.util.naming.LdapAttrs;
 import org.argeo.util.naming.LdapObjs;
 import org.eclipse.jface.window.Window;
-import org.eclipse.jface.wizard.Wizard;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
 import org.eclipse.swt.layout.GridData;
@@ -240,8 +237,9 @@ public class PeopleEntryArea implements SwtUiProvider, CmsUiProvider {
                });
 
                addItem.addSelectionListener((Selected) (e) -> {
-                       // SuiteUtils.getOrCreateUserNode(adminSession, userDn);
-                       GuidedForm wizard = new NewUserWizard(null);
+                       HierarchyUnit hierarchyUnit = usersPart.getInput();
+                       Content huContent = ContentUtils.hierarchyUnitToContent(contentSession, hierarchyUnit);
+                       GuidedForm wizard = new NewUserForm(cmsUserManager, huContent);
                        SwtGuidedFormDialog dialog = new SwtGuidedFormDialog(parent.getShell(), wizard);
                        // WizardDialog dialog = new WizardDialog(shell, wizard);
                        if (dialog.open() == Window.OK) {