View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.cms.e4.users.handlers;
17  
18  import java.util.Dictionary;
19  import java.util.List;
20  import java.util.Map;
21  
22  import javax.inject.Inject;
23  import javax.naming.InvalidNameException;
24  import javax.naming.ldap.LdapName;
25  import javax.naming.ldap.Rdn;
26  
27  import org.argeo.cms.CmsException;
28  import org.argeo.cms.auth.UserAdminUtils;
29  import org.argeo.cms.e4.users.UiAdminUtils;
30  import org.argeo.cms.e4.users.UserAdminWrapper;
31  import org.argeo.eclipse.ui.EclipseUiUtils;
32  import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
33  import org.argeo.naming.LdapAttrs;
34  import org.argeo.osgi.useradmin.UserAdminConf;
35  import org.eclipse.e4.core.di.annotations.Execute;
36  import org.eclipse.jface.wizard.Wizard;
37  import org.eclipse.jface.wizard.WizardDialog;
38  import org.eclipse.jface.wizard.WizardPage;
39  import org.eclipse.swt.SWT;
40  import org.eclipse.swt.events.ModifyEvent;
41  import org.eclipse.swt.events.ModifyListener;
42  import org.eclipse.swt.layout.GridData;
43  import org.eclipse.swt.layout.GridLayout;
44  import org.eclipse.swt.widgets.Combo;
45  import org.eclipse.swt.widgets.Composite;
46  import org.eclipse.swt.widgets.Display;
47  import org.eclipse.swt.widgets.Label;
48  import org.eclipse.swt.widgets.Text;
49  import org.osgi.service.useradmin.Role;
50  import org.osgi.service.useradmin.User;
51  import org.osgi.service.useradmin.UserAdminEvent;
52  
53  /** Open a wizard that enables creation of a new user. */
54  public class NewUser {
55  	// private final static Log log = LogFactory.getLog(NewUser.class);
56  	// public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".newUser";
57  
58  	/* DEPENDENCY INJECTION */
59  	@Inject
60  	private UserAdminWrapper userAdminWrapper;
61  
62  	@Execute
63  	public Object execute() {
64  		NewUserWizard newUserWizard = new NewUserWizard();
65  		newUserWizard.setWindowTitle("User creation");
66  		WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(), newUserWizard);
67  		dialog.open();
68  		return null;
69  	}
70  
71  	private class NewUserWizard extends Wizard {
72  
73  		// pages
74  		private MainUserInfoWizardPage mainUserInfo;
75  
76  		// End user fields
77  		private Text dNameTxt, usernameTxt, firstNameTxt, lastNameTxt, primaryMailTxt, pwd1Txt, pwd2Txt;
78  		private Combo baseDnCmb;
79  
80  		public NewUserWizard() {
81  
82  		}
83  
84  		@Override
85  		public void addPages() {
86  			mainUserInfo = new MainUserInfoWizardPage();
87  			addPage(mainUserInfo);
88  			String message = "Default wizard that also eases user creation tests:\n "
89  					+ "Mail and last name are automatically "
90  					+ "generated form the uid. Password are defauted to 'demo'.";
91  			mainUserInfo.setMessage(message, WizardPage.WARNING);
92  		}
93  
94  		@SuppressWarnings({ "rawtypes", "unchecked" })
95  		@Override
96  		public boolean performFinish() {
97  			if (!canFinish())
98  				return false;
99  			String username = mainUserInfo.getUsername();
100 			userAdminWrapper.beginTransactionIfNeeded();
101 			try {
102 				User user = (User) userAdminWrapper.getUserAdmin().createRole(getDn(username), Role.USER);
103 
104 				Dictionary props = user.getProperties();
105 
106 				String lastNameStr = lastNameTxt.getText();
107 				if (EclipseUiUtils.notEmpty(lastNameStr))
108 					props.put(LdapAttrs.sn.name(), lastNameStr);
109 
110 				String firstNameStr = firstNameTxt.getText();
111 				if (EclipseUiUtils.notEmpty(firstNameStr))
112 					props.put(LdapAttrs.givenName.name(), firstNameStr);
113 
114 				String cn = UserAdminUtils.buildDefaultCn(firstNameStr, lastNameStr);
115 				if (EclipseUiUtils.notEmpty(cn))
116 					props.put(LdapAttrs.cn.name(), cn);
117 
118 				String mailStr = primaryMailTxt.getText();
119 				if (EclipseUiUtils.notEmpty(mailStr))
120 					props.put(LdapAttrs.mail.name(), mailStr);
121 
122 				char[] password = mainUserInfo.getPassword();
123 				user.getCredentials().put(null, password);
124 				userAdminWrapper.commitOrNotifyTransactionStateChange();
125 				userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CREATED, user));
126 				return true;
127 			} catch (Exception e) {
128 				ErrorFeedback.show("Cannot create new user " + username, e);
129 				return false;
130 			}
131 		}
132 
133 		private class MainUserInfoWizardPage extends WizardPage implements ModifyListener {
134 			private static final long serialVersionUID = -3150193365151601807L;
135 
136 			public MainUserInfoWizardPage() {
137 				super("Main");
138 				setTitle("Required Information");
139 			}
140 
141 			@Override
142 			public void createControl(Composite parent) {
143 				Composite composite = new Composite(parent, SWT.NONE);
144 				composite.setLayout(new GridLayout(2, false));
145 				dNameTxt = EclipseUiUtils.createGridLT(composite, "Distinguished name", this);
146 				dNameTxt.setEnabled(false);
147 
148 				baseDnCmb = createGridLC(composite, "Base DN");
149 				initialiseDnCmb(baseDnCmb);
150 				baseDnCmb.addModifyListener(this);
151 				baseDnCmb.addModifyListener(new ModifyListener() {
152 					private static final long serialVersionUID = -1435351236582736843L;
153 
154 					@Override
155 					public void modifyText(ModifyEvent event) {
156 						String name = usernameTxt.getText();
157 						dNameTxt.setText(getDn(name));
158 					}
159 				});
160 
161 				usernameTxt = EclipseUiUtils.createGridLT(composite, "Local ID", this);
162 				usernameTxt.addModifyListener(new ModifyListener() {
163 					private static final long serialVersionUID = -1435351236582736843L;
164 
165 					@Override
166 					public void modifyText(ModifyEvent event) {
167 						String name = usernameTxt.getText();
168 						if (name.trim().equals("")) {
169 							dNameTxt.setText("");
170 							lastNameTxt.setText("");
171 							primaryMailTxt.setText("");
172 							pwd1Txt.setText("");
173 							pwd2Txt.setText("");
174 						} else {
175 							dNameTxt.setText(getDn(name));
176 							lastNameTxt.setText(name.toUpperCase());
177 							primaryMailTxt.setText(getMail(name));
178 							pwd1Txt.setText("demo");
179 							pwd2Txt.setText("demo");
180 						}
181 					}
182 				});
183 
184 				primaryMailTxt = EclipseUiUtils.createGridLT(composite, "Email", this);
185 				firstNameTxt = EclipseUiUtils.createGridLT(composite, "First name", this);
186 				lastNameTxt = EclipseUiUtils.createGridLT(composite, "Last name", this);
187 				pwd1Txt = EclipseUiUtils.createGridLP(composite, "Password", this);
188 				pwd2Txt = EclipseUiUtils.createGridLP(composite, "Repeat password", this);
189 				setControl(composite);
190 
191 				// Initialize buttons
192 				setPageComplete(false);
193 				getContainer().updateButtons();
194 			}
195 
196 			@Override
197 			public void modifyText(ModifyEvent event) {
198 				String message = checkComplete();
199 				if (message != null) {
200 					setMessage(message, WizardPage.ERROR);
201 					setPageComplete(false);
202 				} else {
203 					setMessage("Complete", WizardPage.INFORMATION);
204 					setPageComplete(true);
205 				}
206 				getContainer().updateButtons();
207 			}
208 
209 			/** @return error message or null if complete */
210 			protected String checkComplete() {
211 				String name = usernameTxt.getText();
212 
213 				if (name.trim().equals(""))
214 					return "User name must not be empty";
215 				Role role = userAdminWrapper.getUserAdmin().getRole(getDn(name));
216 				if (role != null)
217 					return "User " + name + " already exists";
218 				if (!primaryMailTxt.getText().matches(UiAdminUtils.EMAIL_PATTERN))
219 					return "Not a valid email address";
220 				if (lastNameTxt.getText().trim().equals(""))
221 					return "Specify a last name";
222 				if (pwd1Txt.getText().trim().equals(""))
223 					return "Specify a password";
224 				if (pwd2Txt.getText().trim().equals(""))
225 					return "Repeat the password";
226 				if (!pwd2Txt.getText().equals(pwd1Txt.getText()))
227 					return "Passwords are different";
228 				return null;
229 			}
230 
231 			@Override
232 			public void setVisible(boolean visible) {
233 				super.setVisible(visible);
234 				if (visible)
235 					if (baseDnCmb.getSelectionIndex() == -1)
236 						baseDnCmb.setFocus();
237 					else
238 						usernameTxt.setFocus();
239 			}
240 
241 			public String getUsername() {
242 				return usernameTxt.getText();
243 			}
244 
245 			public char[] getPassword() {
246 				return pwd1Txt.getTextChars();
247 			}
248 
249 		}
250 
251 		private Map<String, String> getDns() {
252 			return userAdminWrapper.getKnownBaseDns(true);
253 		}
254 
255 		private String getDn(String uid) {
256 			Map<String, String> dns = getDns();
257 			String bdn = baseDnCmb.getText();
258 			if (EclipseUiUtils.notEmpty(bdn)) {
259 				Dictionary<String, ?> props = UserAdminConf.uriAsProperties(dns.get(bdn));
260 				String dn = LdapAttrs.uid.name() + "=" + uid + "," + UserAdminConf.userBase.getValue(props) + "," + bdn;
261 				return dn;
262 			}
263 			return null;
264 		}
265 
266 		private void initialiseDnCmb(Combo combo) {
267 			Map<String, String> dns = userAdminWrapper.getKnownBaseDns(true);
268 			if (dns.isEmpty())
269 				throw new CmsException("No writable base dn found. Cannot create user");
270 			combo.setItems(dns.keySet().toArray(new String[0]));
271 			if (dns.size() == 1)
272 				combo.select(0);
273 		}
274 
275 		private String getMail(String username) {
276 			if (baseDnCmb.getSelectionIndex() == -1)
277 				return null;
278 			String baseDn = baseDnCmb.getText();
279 			try {
280 				LdapName name = new LdapName(baseDn);
281 				List<Rdn> rdns = name.getRdns();
282 				return username + "@" + (String) rdns.get(1).getValue() + '.' + (String) rdns.get(0).getValue();
283 			} catch (InvalidNameException e) {
284 				throw new CmsException("Unable to generate mail for " + username + " with base dn " + baseDn, e);
285 			}
286 		}
287 	}
288 
289 	private Combo createGridLC(Composite parent, String label) {
290 		Label lbl = new Label(parent, SWT.LEAD);
291 		lbl.setText(label);
292 		lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
293 		Combo combo = new Combo(parent, SWT.LEAD | SWT.BORDER | SWT.READ_ONLY);
294 		combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
295 		return combo;
296 	}
297 
298 	/* DEPENDENCY INJECTION */
299 	public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
300 		this.userAdminWrapper = userAdminWrapper;
301 	}
302 }