]> git.argeo.org Git - lgpl/argeo-commons.git/blob - e4/users/UserEditor.java
Prepare next development cycle
[lgpl/argeo-commons.git] / e4 / users / UserEditor.java
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;
17
18 import static org.argeo.cms.util.UserAdminUtils.getProperty;
19 import static org.argeo.naming.LdapAttrs.cn;
20 import static org.argeo.naming.LdapAttrs.givenName;
21 import static org.argeo.naming.LdapAttrs.mail;
22 import static org.argeo.naming.LdapAttrs.sn;
23 import static org.argeo.naming.LdapAttrs.uid;
24
25 import java.util.ArrayList;
26 import java.util.Iterator;
27 import java.util.List;
28
29 import javax.inject.Inject;
30
31 import org.argeo.cms.auth.CurrentUser;
32 import org.argeo.cms.e4.users.providers.CommonNameLP;
33 import org.argeo.cms.e4.users.providers.DomainNameLP;
34 import org.argeo.cms.e4.users.providers.RoleIconLP;
35 import org.argeo.cms.e4.users.providers.UserFilter;
36 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
37 //import org.argeo.cms.ui.eclipse.forms.FormToolkit;
38 import org.argeo.cms.ui.eclipse.forms.IManagedForm;
39 import org.argeo.cms.util.CmsUtils;
40 import org.argeo.cms.util.UserAdminUtils;
41 import org.argeo.eclipse.ui.ColumnDefinition;
42 import org.argeo.eclipse.ui.EclipseUiUtils;
43 import org.argeo.eclipse.ui.parts.LdifUsersTable;
44 import org.argeo.naming.LdapAttrs;
45 import org.argeo.node.NodeConstants;
46 import org.eclipse.e4.ui.workbench.modeling.EPartService;
47 import org.eclipse.jface.action.Action;
48 import org.eclipse.jface.action.ToolBarManager;
49 import org.eclipse.jface.dialogs.MessageDialog;
50 import org.eclipse.jface.dialogs.TrayDialog;
51 import org.eclipse.jface.resource.ImageDescriptor;
52 import org.eclipse.jface.viewers.ISelection;
53 import org.eclipse.jface.viewers.IStructuredSelection;
54 import org.eclipse.jface.viewers.TableViewer;
55 import org.eclipse.jface.viewers.Viewer;
56 import org.eclipse.jface.viewers.ViewerDropAdapter;
57 import org.eclipse.swt.SWT;
58 import org.eclipse.swt.dnd.DND;
59 import org.eclipse.swt.dnd.DropTargetEvent;
60 import org.eclipse.swt.dnd.TextTransfer;
61 import org.eclipse.swt.dnd.Transfer;
62 import org.eclipse.swt.dnd.TransferData;
63 import org.eclipse.swt.events.ModifyEvent;
64 import org.eclipse.swt.events.ModifyListener;
65 import org.eclipse.swt.events.SelectionAdapter;
66 import org.eclipse.swt.events.SelectionEvent;
67 import org.eclipse.swt.layout.GridData;
68 import org.eclipse.swt.layout.GridLayout;
69 import org.eclipse.swt.widgets.Button;
70 import org.eclipse.swt.widgets.Composite;
71 import org.eclipse.swt.widgets.Control;
72 import org.eclipse.swt.widgets.Display;
73 import org.eclipse.swt.widgets.Link;
74 import org.eclipse.swt.widgets.Shell;
75 import org.eclipse.swt.widgets.Text;
76 import org.eclipse.swt.widgets.ToolBar;
77 import org.osgi.service.useradmin.Group;
78 import org.osgi.service.useradmin.Role;
79 import org.osgi.service.useradmin.User;
80 import org.osgi.service.useradmin.UserAdmin;
81 import org.osgi.service.useradmin.UserAdminEvent;
82
83 /** Display/edit the properties of a given user */
84 public class UserEditor extends AbstractRoleEditor {
85 // final static String ID = "UserEditor.mainPage";
86
87 @Inject
88 private EPartService partService;
89
90 // private final UserEditor editor;
91 // private UserAdminWrapper userAdminWrapper;
92
93 // Local configuration
94 // private final int PRE_TITLE_INDENT = 10;
95
96 // public UserMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper) {
97 // super(editor, ID, "Main");
98 // this.editor = (UserEditor) editor;
99 // this.userAdminWrapper = userAdminWrapper;
100 // }
101
102 // protected void createFormContent(final IManagedForm mf) {
103 // ScrolledForm form = mf.getForm();
104 // Composite body = form.getBody();
105 // GridLayout mainLayout = new GridLayout();
106 // // mainLayout.marginRight = 10;
107 // body.setLayout(mainLayout);
108 // User user = editor.getDisplayedUser();
109 // appendOverviewPart(body, user);
110 // // Remove to ability to force the password for his own user. The user
111 // // must then use the change pwd feature
112 // appendMemberOfPart(body, user);
113 // }
114
115 @Override
116 protected void createUi(Composite body) {
117 // Composite body = new Composite(parent, SWT.BORDER);
118 GridLayout mainLayout = new GridLayout();
119 // mainLayout.marginRight = 10;
120 body.setLayout(mainLayout);
121 // body.getParent().setLayout(new GridLayout());
122 // body.setLayoutData(CmsUtils.fillAll());
123 User user = getDisplayedUser();
124 appendOverviewPart(body, user);
125 // Remove to ability to force the password for his own user. The user
126 // must then use the change pwd feature
127 appendMemberOfPart(body, user);
128 }
129
130 /** Creates the general section */
131 private void appendOverviewPart(final Composite parent, final User user) {
132 // FormToolkit tk = getManagedForm().getToolkit();
133
134 // Section section = tk.createSection(parent, SWT.NO_FOCUS);
135 // GridData gd = EclipseUiUtils.fillWidth();
136 // // gd.verticalAlignment = PRE_TITLE_INDENT;
137 // section.setLayoutData(gd);
138 Composite body = new Composite(parent, SWT.NONE);
139 body.setLayoutData(EclipseUiUtils.fillWidth());
140 // section.setClient(body);
141 // body.setLayout(new GridLayout(6, false));
142 body.setLayout(new GridLayout(2, false));
143
144 Text commonName = createReadOnlyLT(body, "Name", getProperty(user, cn));
145 Text distinguishedName = createReadOnlyLT(body, "Login", getProperty(user, uid));
146 Text firstName = createLT(body, "First name", getProperty(user, givenName));
147 Text lastName = createLT(body, "Last name", getProperty(user, sn));
148 Text email = createLT(body, "Email", getProperty(user, mail));
149
150 Link resetPwdLk = new Link(body, SWT.NONE);
151 if (!UserAdminUtils.isCurrentUser(user)) {
152 resetPwdLk.setText("<a>Reset password</a>");
153 }
154 resetPwdLk.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
155
156 // create form part (controller)
157 AbstractFormPart part = new AbstractFormPart() {
158 private MainInfoListener listener;
159
160 @Override
161 public void initialize(IManagedForm form) {
162 super.initialize(form);
163 listener = new MainInfoListener(parent.getDisplay(), this);
164 userAdminWrapper.addListener(listener);
165 }
166
167 @Override
168 public void dispose() {
169 userAdminWrapper.removeListener(listener);
170 super.dispose();
171 }
172
173 @SuppressWarnings("unchecked")
174 public void commit(boolean onSave) {
175 // TODO Sanity checks (mail validity...)
176 user.getProperties().put(LdapAttrs.givenName.name(), firstName.getText());
177 user.getProperties().put(LdapAttrs.sn.name(), lastName.getText());
178 user.getProperties().put(LdapAttrs.cn.name(), commonName.getText());
179 user.getProperties().put(LdapAttrs.mail.name(), email.getText());
180 super.commit(onSave);
181 }
182
183 @Override
184 public void refresh() {
185 distinguishedName.setText(UserAdminUtils.getProperty(user, LdapAttrs.uid.name()));
186 commonName.setText(UserAdminUtils.getProperty(user, LdapAttrs.cn.name()));
187 firstName.setText(UserAdminUtils.getProperty(user, LdapAttrs.givenName.name()));
188 lastName.setText(UserAdminUtils.getProperty(user, LdapAttrs.sn.name()));
189 email.setText(UserAdminUtils.getProperty(user, LdapAttrs.mail.name()));
190 refreshFormTitle(user);
191 super.refresh();
192 }
193 };
194
195 // Improve this: automatically generate CN when first or last name
196 // changes
197 ModifyListener cnML = new ModifyListener() {
198 private static final long serialVersionUID = 4298649222869835486L;
199
200 @Override
201 public void modifyText(ModifyEvent event) {
202 String first = firstName.getText();
203 String last = lastName.getText();
204 String cn = first.trim() + " " + last.trim() + " ";
205 cn = cn.trim();
206 commonName.setText(cn);
207 // getManagedForm().getForm().setText(cn);
208 updateEditorTitle(cn);
209 }
210 };
211 firstName.addModifyListener(cnML);
212 lastName.addModifyListener(cnML);
213
214 ModifyListener defaultListener = new FormPartML(part);
215 firstName.addModifyListener(defaultListener);
216 lastName.addModifyListener(defaultListener);
217 email.addModifyListener(defaultListener);
218
219 if (!UserAdminUtils.isCurrentUser(user))
220 resetPwdLk.addSelectionListener(new SelectionAdapter() {
221 private static final long serialVersionUID = 5881800534589073787L;
222
223 @Override
224 public void widgetSelected(SelectionEvent e) {
225 new ChangePasswordDialog(user, "Reset password").open();
226 }
227 });
228
229 getManagedForm().addPart(part);
230 }
231
232 private class ChangePasswordDialog extends TrayDialog {
233 private static final long serialVersionUID = 2843538207460082349L;
234
235 private User user;
236 private Text password1;
237 private Text password2;
238 private String title;
239 // private FormToolkit tk;
240
241 public ChangePasswordDialog(User user, String title) {
242 super(Display.getDefault().getActiveShell());
243 // this.tk = tk;
244 this.user = user;
245 this.title = title;
246 }
247
248 protected Control createDialogArea(Composite parent) {
249 Composite dialogarea = (Composite) super.createDialogArea(parent);
250 dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
251 Composite body = new Composite(dialogarea, SWT.NO_FOCUS);
252 body.setLayoutData(EclipseUiUtils.fillAll());
253 GridLayout layout = new GridLayout(2, false);
254 body.setLayout(layout);
255
256 password1 = createLP(body, "New password", "");
257 password2 = createLP(body, "Repeat password", "");
258 parent.pack();
259 return body;
260 }
261
262 @SuppressWarnings("unchecked")
263 @Override
264 protected void okPressed() {
265 String msg = null;
266
267 if (password1.getText().equals(""))
268 msg = "Password cannot be empty";
269 else if (password1.getText().equals(password2.getText())) {
270 char[] newPassword = password1.getText().toCharArray();
271 // userAdminWrapper.beginTransactionIfNeeded();
272 userAdminWrapper.beginTransactionIfNeeded();
273 user.getCredentials().put(null, newPassword);
274 userAdminWrapper.commitOrNotifyTransactionStateChange();
275 super.okPressed();
276 } else {
277 msg = "Passwords are not equals";
278 }
279
280 if (EclipseUiUtils.notEmpty(msg))
281 MessageDialog.openError(getParentShell(), "Cannot reset pasword", msg);
282 }
283
284 protected void configureShell(Shell shell) {
285 super.configureShell(shell);
286 shell.setText(title);
287 }
288 }
289
290 private LdifUsersTable appendMemberOfPart(final Composite parent, User user) {
291 // Section section = addSection(tk, parent, "Roles");
292 // Composite body = (Composite) section.getClient();
293 // Composite body= parent;
294 Composite body = new Composite(parent, SWT.BORDER);
295 body.setLayout(new GridLayout());
296 body.setLayoutData(CmsUtils.fillAll());
297
298 // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN);
299
300 // Displayed columns
301 List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
302 columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
303 columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150));
304 columnDefs.add(new ColumnDefinition(new DomainNameLP(), "Domain", 100));
305 // Only show technical DN to administrators
306 // if (isAdmin)
307 // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name",
308 // 300));
309
310 // Create and configure the table
311 final LdifUsersTable userViewerCmp = new MyUserTableViewer(body, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL, user);
312
313 userViewerCmp.setColumnDefinitions(columnDefs);
314 // if (isAdmin)
315 // userViewerCmp.populateWithStaticFilters(false, false);
316 // else
317 userViewerCmp.populate(true, false);
318 GridData gd = EclipseUiUtils.fillAll();
319 gd.heightHint = 500;
320 userViewerCmp.setLayoutData(gd);
321
322 // Controllers
323 TableViewer userViewer = userViewerCmp.getTableViewer();
324 userViewer.addDoubleClickListener(new UserTableDefaultDClickListener(partService));
325 int operations = DND.DROP_COPY | DND.DROP_MOVE;
326 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
327 GroupDropListener dropL = new GroupDropListener(userAdminWrapper, userViewer, user);
328 userViewer.addDropSupport(operations, tt, dropL);
329
330 AbstractFormPart part = new AbstractFormPart() {
331
332 private GroupChangeListener listener;
333
334 @Override
335 public void initialize(IManagedForm form) {
336 super.initialize(form);
337 listener = new GroupChangeListener(parent.getDisplay(), this);
338 userAdminWrapper.addListener(listener);
339 }
340
341 public void commit(boolean onSave) {
342 super.commit(onSave);
343 }
344
345 @Override
346 public void dispose() {
347 userAdminWrapper.removeListener(listener);
348 super.dispose();
349 }
350
351 @Override
352 public void refresh() {
353 userViewerCmp.refresh();
354 super.refresh();
355 }
356 };
357 getManagedForm().addPart(part);
358 // addRemoveAbitily(body, userViewer, user);
359 // userViewerCmp.refresh();
360 String tooltip = "Remove " + UserAdminUtils.getUserLocalId(user.getName()) + " from the below selected groups";
361 Action action = new RemoveMembershipAction(userViewer, user, tooltip, SecurityAdminImages.ICON_REMOVE_DESC);
362 ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
363 ToolBar toolBar = toolBarManager.createControl(body);
364 toolBar.setLayoutData(CmsUtils.fillWidth());
365 toolBarManager.add(action);
366 toolBarManager.update(true);
367 return userViewerCmp;
368 }
369
370 private class MyUserTableViewer extends LdifUsersTable {
371 private static final long serialVersionUID = 2653790051461237329L;
372
373 private Button showSystemRoleBtn;
374
375 private final User user;
376 private final UserFilter userFilter;
377
378 public MyUserTableViewer(Composite parent, int style, User user) {
379 super(parent, style, true);
380 this.user = user;
381 userFilter = new UserFilter();
382 }
383
384 protected void populateStaticFilters(Composite staticFilterCmp) {
385 staticFilterCmp.setLayout(new GridLayout());
386 showSystemRoleBtn = new Button(staticFilterCmp, SWT.CHECK);
387 showSystemRoleBtn.setText("Show system roles");
388 boolean showSysRole = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN);
389 showSystemRoleBtn.setSelection(showSysRole);
390 userFilter.setShowSystemRole(showSysRole);
391 showSystemRoleBtn.addSelectionListener(new SelectionAdapter() {
392 private static final long serialVersionUID = -7033424592697691676L;
393
394 @Override
395 public void widgetSelected(SelectionEvent e) {
396 userFilter.setShowSystemRole(showSystemRoleBtn.getSelection());
397 refresh();
398 }
399 });
400 }
401
402 @Override
403 protected List<User> listFilteredElements(String filter) {
404 List<User> users = (List<User>) getFlatGroups(null);
405 List<User> filteredUsers = new ArrayList<User>();
406 if (users.contains(user))
407 users.remove(user);
408 userFilter.setSearchText(filter);
409 for (User user : users)
410 if (userFilter.select(null, null, user))
411 filteredUsers.add(user);
412 return filteredUsers;
413 }
414 }
415
416 // private void addRemoveAbility(Composite parent, TableViewer userViewer, User
417 // user) {
418 // // Section section = sectionPart.getSection();
419 // ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
420 // ToolBar toolbar = toolBarManager.createControl(parent);
421 // final Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
422 // toolbar.setCursor(handCursor);
423 // toolbar.addDisposeListener(new DisposeListener() {
424 // private static final long serialVersionUID = 3882131405820522925L;
425 //
426 // public void widgetDisposed(DisposeEvent e) {
427 // if ((handCursor != null) && (handCursor.isDisposed() == false)) {
428 // handCursor.dispose();
429 // }
430 // }
431 // });
432 //
433 // String tooltip = "Remove " + UserAdminUtils.getUserLocalId(user.getName()) +
434 // " from the below selected groups";
435 // Action action = new RemoveMembershipAction(userViewer, user, tooltip,
436 // SecurityAdminImages.ICON_REMOVE_DESC);
437 // toolBarManager.add(action);
438 // toolBarManager.update(true);
439 // // section.setTextClient(toolbar);
440 // }
441
442 private class RemoveMembershipAction extends Action {
443 private static final long serialVersionUID = -1337713097184522588L;
444
445 private final TableViewer userViewer;
446 private final User user;
447
448 RemoveMembershipAction(TableViewer userViewer, User user, String name, ImageDescriptor img) {
449 super(name, img);
450 this.userViewer = userViewer;
451 this.user = user;
452 }
453
454 @Override
455 public void run() {
456 ISelection selection = userViewer.getSelection();
457 if (selection.isEmpty())
458 return;
459
460 @SuppressWarnings("unchecked")
461 Iterator<Group> it = ((IStructuredSelection) selection).iterator();
462 List<Group> groups = new ArrayList<Group>();
463 while (it.hasNext()) {
464 Group currGroup = it.next();
465 groups.add(currGroup);
466 }
467
468 userAdminWrapper.beginTransactionIfNeeded();
469 for (Group group : groups) {
470 group.removeMember(user);
471 }
472 userAdminWrapper.commitOrNotifyTransactionStateChange();
473 for (Group group : groups) {
474 userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group));
475 }
476 }
477 }
478
479 /**
480 * Defines the table as being a potential target to add group memberships
481 * (roles) to this user
482 */
483 private class GroupDropListener extends ViewerDropAdapter {
484 private static final long serialVersionUID = 2893468717831451621L;
485
486 private final UserAdminWrapper myUserAdminWrapper;
487 private final User myUser;
488
489 public GroupDropListener(UserAdminWrapper userAdminWrapper, Viewer userViewer, User user) {
490 super(userViewer);
491 this.myUserAdminWrapper = userAdminWrapper;
492 this.myUser = user;
493 }
494
495 @Override
496 public boolean validateDrop(Object target, int operation, TransferData transferType) {
497 // Target is always OK in a list only view
498 // TODO check if not a string
499 boolean validDrop = true;
500 return validDrop;
501 }
502
503 @Override
504 public void drop(DropTargetEvent event) {
505 String name = (String) event.data;
506 UserAdmin myUserAdmin = myUserAdminWrapper.getUserAdmin();
507 Role role = myUserAdmin.getRole(name);
508 // TODO this check should be done before.
509 if (role.getType() == Role.GROUP) {
510 // TODO check if the user is already member of this group
511
512 myUserAdminWrapper.beginTransactionIfNeeded();
513 Group group = (Group) role;
514 group.addMember(myUser);
515 userAdminWrapper.commitOrNotifyTransactionStateChange();
516 myUserAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group));
517 }
518 super.drop(event);
519 }
520
521 @Override
522 public boolean performDrop(Object data) {
523 // userTableViewerCmp.refresh();
524 return true;
525 }
526 }
527
528 // LOCAL HELPERS
529 private void refreshFormTitle(User group) {
530 // getManagedForm().getForm().setText(UserAdminUtils.getProperty(group,
531 // LdapAttrs.cn.name()));
532 }
533
534 /** Appends a section with a title */
535 // private Section addSection(FormToolkit tk, Composite parent, String title) {
536 // Section section = tk.createSection(parent, Section.TITLE_BAR);
537 // GridData gd = EclipseUiUtils.fillWidth();
538 // gd.verticalAlignment = PRE_TITLE_INDENT;
539 // section.setLayoutData(gd);
540 // section.setText(title);
541 // // section.getMenu().setVisible(true);
542 //
543 // Composite body = tk.createComposite(section, SWT.WRAP);
544 // body.setLayoutData(EclipseUiUtils.fillAll());
545 // section.setClient(body);
546 //
547 // return section;
548 // }
549
550 }