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