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