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