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