2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.cms
.e4
.users
;
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
;
25 import java
.util
.ArrayList
;
26 import java
.util
.Iterator
;
27 import java
.util
.List
;
29 import javax
.inject
.Inject
;
31 import org
.argeo
.cms
.ArgeoNames
;
32 import org
.argeo
.cms
.auth
.CurrentUser
;
33 import org
.argeo
.cms
.e4
.users
.providers
.CommonNameLP
;
34 import org
.argeo
.cms
.e4
.users
.providers
.DomainNameLP
;
35 import org
.argeo
.cms
.e4
.users
.providers
.RoleIconLP
;
36 import org
.argeo
.cms
.e4
.users
.providers
.UserFilter
;
37 import org
.argeo
.cms
.ui
.eclipse
.forms
.AbstractFormPart
;
38 //import org.argeo.cms.ui.eclipse.forms.FormToolkit;
39 import org
.argeo
.cms
.ui
.eclipse
.forms
.IManagedForm
;
40 import org
.argeo
.cms
.util
.CmsUtils
;
41 import org
.argeo
.cms
.util
.UserAdminUtils
;
42 import org
.argeo
.eclipse
.ui
.ColumnDefinition
;
43 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
44 import org
.argeo
.eclipse
.ui
.parts
.LdifUsersTable
;
45 import org
.argeo
.naming
.LdapAttrs
;
46 import org
.argeo
.node
.NodeConstants
;
47 import org
.eclipse
.e4
.ui
.workbench
.modeling
.EPartService
;
48 import org
.eclipse
.jface
.action
.Action
;
49 import org
.eclipse
.jface
.action
.ToolBarManager
;
50 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
51 import org
.eclipse
.jface
.dialogs
.TrayDialog
;
52 import org
.eclipse
.jface
.resource
.ImageDescriptor
;
53 import org
.eclipse
.jface
.viewers
.ISelection
;
54 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
55 import org
.eclipse
.jface
.viewers
.TableViewer
;
56 import org
.eclipse
.jface
.viewers
.Viewer
;
57 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
58 import org
.eclipse
.swt
.SWT
;
59 import org
.eclipse
.swt
.dnd
.DND
;
60 import org
.eclipse
.swt
.dnd
.DropTargetEvent
;
61 import org
.eclipse
.swt
.dnd
.TextTransfer
;
62 import org
.eclipse
.swt
.dnd
.Transfer
;
63 import org
.eclipse
.swt
.dnd
.TransferData
;
64 import org
.eclipse
.swt
.events
.ModifyEvent
;
65 import org
.eclipse
.swt
.events
.ModifyListener
;
66 import org
.eclipse
.swt
.events
.SelectionAdapter
;
67 import org
.eclipse
.swt
.events
.SelectionEvent
;
68 import org
.eclipse
.swt
.layout
.GridData
;
69 import org
.eclipse
.swt
.layout
.GridLayout
;
70 import org
.eclipse
.swt
.widgets
.Button
;
71 import org
.eclipse
.swt
.widgets
.Composite
;
72 import org
.eclipse
.swt
.widgets
.Control
;
73 import org
.eclipse
.swt
.widgets
.Display
;
74 import org
.eclipse
.swt
.widgets
.Link
;
75 import org
.eclipse
.swt
.widgets
.Shell
;
76 import org
.eclipse
.swt
.widgets
.Text
;
77 import org
.eclipse
.swt
.widgets
.ToolBar
;
78 import org
.osgi
.service
.useradmin
.Group
;
79 import org
.osgi
.service
.useradmin
.Role
;
80 import org
.osgi
.service
.useradmin
.User
;
81 import org
.osgi
.service
.useradmin
.UserAdmin
;
82 import org
.osgi
.service
.useradmin
.UserAdminEvent
;
84 /** Display/edit the properties of a given user */
85 public class UserEditor
extends AbstractRoleEditor
implements ArgeoNames
{
86 // final static String ID = "UserEditor.mainPage";
89 private EPartService partService
;
91 // private final UserEditor editor;
92 // private UserAdminWrapper userAdminWrapper;
94 // Local configuration
95 // private final int PRE_TITLE_INDENT = 10;
97 // public UserMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper) {
98 // super(editor, ID, "Main");
99 // this.editor = (UserEditor) editor;
100 // this.userAdminWrapper = userAdminWrapper;
103 // protected void createFormContent(final IManagedForm mf) {
104 // ScrolledForm form = mf.getForm();
105 // Composite body = form.getBody();
106 // GridLayout mainLayout = new GridLayout();
107 // // mainLayout.marginRight = 10;
108 // body.setLayout(mainLayout);
109 // User user = editor.getDisplayedUser();
110 // appendOverviewPart(body, user);
111 // // Remove to ability to force the password for his own user. The user
112 // // must then use the change pwd feature
113 // appendMemberOfPart(body, user);
117 protected void createUi(Composite body
) {
118 // Composite body = new Composite(parent, SWT.BORDER);
119 GridLayout mainLayout
= new GridLayout();
120 // mainLayout.marginRight = 10;
121 body
.setLayout(mainLayout
);
122 // body.getParent().setLayout(new GridLayout());
123 // body.setLayoutData(CmsUtils.fillAll());
124 User user
= getDisplayedUser();
125 appendOverviewPart(body
, user
);
126 // Remove to ability to force the password for his own user. The user
127 // must then use the change pwd feature
128 appendMemberOfPart(body
, user
);
131 /** Creates the general section */
132 private void appendOverviewPart(final Composite parent
, final User user
) {
133 // FormToolkit tk = getManagedForm().getToolkit();
135 // Section section = tk.createSection(parent, SWT.NO_FOCUS);
136 // GridData gd = EclipseUiUtils.fillWidth();
137 // // gd.verticalAlignment = PRE_TITLE_INDENT;
138 // section.setLayoutData(gd);
139 Composite body
= new Composite(parent
, SWT
.NONE
);
140 body
.setLayoutData(EclipseUiUtils
.fillWidth());
141 // section.setClient(body);
142 // body.setLayout(new GridLayout(6, false));
143 body
.setLayout(new GridLayout(2, false));
145 Text commonName
= createReadOnlyLT(body
, "Name", getProperty(user
, cn
));
146 Text distinguishedName
= createReadOnlyLT(body
, "Login", getProperty(user
, uid
));
147 Text firstName
= createLT(body
, "First name", getProperty(user
, givenName
));
148 Text lastName
= createLT(body
, "Last name", getProperty(user
, sn
));
149 Text email
= createLT(body
, "Email", getProperty(user
, mail
));
151 Link resetPwdLk
= new Link(body
, SWT
.NONE
);
152 if (!UserAdminUtils
.isCurrentUser(user
)) {
153 resetPwdLk
.setText("<a>Reset password</a>");
155 resetPwdLk
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false, 2, 1));
157 // create form part (controller)
158 AbstractFormPart part
= new AbstractFormPart() {
159 private MainInfoListener listener
;
162 public void initialize(IManagedForm form
) {
163 super.initialize(form
);
164 listener
= new MainInfoListener(parent
.getDisplay(), this);
165 userAdminWrapper
.addListener(listener
);
169 public void dispose() {
170 userAdminWrapper
.removeListener(listener
);
174 @SuppressWarnings("unchecked")
175 public void commit(boolean onSave
) {
176 // TODO Sanity checks (mail validity...)
177 user
.getProperties().put(LdapAttrs
.givenName
.name(), firstName
.getText());
178 user
.getProperties().put(LdapAttrs
.sn
.name(), lastName
.getText());
179 user
.getProperties().put(LdapAttrs
.cn
.name(), commonName
.getText());
180 user
.getProperties().put(LdapAttrs
.mail
.name(), email
.getText());
181 super.commit(onSave
);
185 public void refresh() {
186 distinguishedName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.uid
.name()));
187 commonName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.cn
.name()));
188 firstName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.givenName
.name()));
189 lastName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.sn
.name()));
190 email
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.mail
.name()));
191 refreshFormTitle(user
);
196 // Improve this: automatically generate CN when first or last name
198 ModifyListener cnML
= new ModifyListener() {
199 private static final long serialVersionUID
= 4298649222869835486L;
202 public void modifyText(ModifyEvent event
) {
203 String first
= firstName
.getText();
204 String last
= lastName
.getText();
205 String cn
= first
.trim() + " " + last
.trim() + " ";
207 commonName
.setText(cn
);
208 // getManagedForm().getForm().setText(cn);
209 updateEditorTitle(cn
);
212 firstName
.addModifyListener(cnML
);
213 lastName
.addModifyListener(cnML
);
215 ModifyListener defaultListener
= new FormPartML(part
);
216 firstName
.addModifyListener(defaultListener
);
217 lastName
.addModifyListener(defaultListener
);
218 email
.addModifyListener(defaultListener
);
220 if (!UserAdminUtils
.isCurrentUser(user
))
221 resetPwdLk
.addSelectionListener(new SelectionAdapter() {
222 private static final long serialVersionUID
= 5881800534589073787L;
225 public void widgetSelected(SelectionEvent e
) {
226 new ChangePasswordDialog(user
, "Reset password").open();
230 getManagedForm().addPart(part
);
233 private class ChangePasswordDialog
extends TrayDialog
{
234 private static final long serialVersionUID
= 2843538207460082349L;
237 private Text password1
;
238 private Text password2
;
239 private String title
;
240 // private FormToolkit tk;
242 public ChangePasswordDialog(User user
, String title
) {
243 super(Display
.getDefault().getActiveShell());
249 protected Control
createDialogArea(Composite parent
) {
250 Composite dialogarea
= (Composite
) super.createDialogArea(parent
);
251 dialogarea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
252 Composite body
= new Composite(dialogarea
, SWT
.NO_FOCUS
);
253 body
.setLayoutData(EclipseUiUtils
.fillAll());
254 GridLayout layout
= new GridLayout(2, false);
255 body
.setLayout(layout
);
257 password1
= createLP(body
, "New password", "");
258 password2
= createLP(body
, "Repeat password", "");
263 @SuppressWarnings("unchecked")
265 protected void okPressed() {
268 if (password1
.getText().equals(""))
269 msg
= "Password cannot be empty";
270 else if (password1
.getText().equals(password2
.getText())) {
271 char[] newPassword
= password1
.getText().toCharArray();
272 // userAdminWrapper.beginTransactionIfNeeded();
273 userAdminWrapper
.beginTransactionIfNeeded();
274 user
.getCredentials().put(null, newPassword
);
275 userAdminWrapper
.commitOrNotifyTransactionStateChange();
278 msg
= "Passwords are not equals";
281 if (EclipseUiUtils
.notEmpty(msg
))
282 MessageDialog
.openError(getParentShell(), "Cannot reset pasword", msg
);
285 protected void configureShell(Shell shell
) {
286 super.configureShell(shell
);
287 shell
.setText(title
);
291 private LdifUsersTable
appendMemberOfPart(final Composite parent
, User user
) {
292 // Section section = addSection(tk, parent, "Roles");
293 // Composite body = (Composite) section.getClient();
294 // Composite body= parent;
295 Composite body
= new Composite(parent
, SWT
.BORDER
);
296 body
.setLayout(new GridLayout());
297 body
.setLayoutData(CmsUtils
.fillAll());
299 // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN);
302 List
<ColumnDefinition
> columnDefs
= new ArrayList
<ColumnDefinition
>();
303 columnDefs
.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
304 columnDefs
.add(new ColumnDefinition(new CommonNameLP(), "Name", 150));
305 columnDefs
.add(new ColumnDefinition(new DomainNameLP(), "Domain", 100));
306 // Only show technical DN to administrators
308 // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name",
311 // Create and configure the table
312 final LdifUsersTable userViewerCmp
= new MyUserTableViewer(body
, SWT
.MULTI
| SWT
.H_SCROLL
| SWT
.V_SCROLL
, user
);
314 userViewerCmp
.setColumnDefinitions(columnDefs
);
316 // userViewerCmp.populateWithStaticFilters(false, false);
318 userViewerCmp
.populate(true, false);
319 GridData gd
= EclipseUiUtils
.fillAll();
321 userViewerCmp
.setLayoutData(gd
);
324 TableViewer userViewer
= userViewerCmp
.getTableViewer();
325 userViewer
.addDoubleClickListener(new UserTableDefaultDClickListener(partService
));
326 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
327 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
328 GroupDropListener dropL
= new GroupDropListener(userAdminWrapper
, userViewer
, user
);
329 userViewer
.addDropSupport(operations
, tt
, dropL
);
331 AbstractFormPart part
= new AbstractFormPart() {
333 private GroupChangeListener listener
;
336 public void initialize(IManagedForm form
) {
337 super.initialize(form
);
338 listener
= new GroupChangeListener(parent
.getDisplay(), this);
339 userAdminWrapper
.addListener(listener
);
342 public void commit(boolean onSave
) {
343 super.commit(onSave
);
347 public void dispose() {
348 userAdminWrapper
.removeListener(listener
);
353 public void refresh() {
354 userViewerCmp
.refresh();
358 getManagedForm().addPart(part
);
359 // addRemoveAbitily(body, userViewer, user);
360 // userViewerCmp.refresh();
361 String tooltip
= "Remove " + UserAdminUtils
.getUserLocalId(user
.getName()) + " from the below selected groups";
362 Action action
= new RemoveMembershipAction(userViewer
, user
, tooltip
, SecurityAdminImages
.ICON_REMOVE_DESC
);
363 ToolBarManager toolBarManager
= new ToolBarManager(SWT
.FLAT
);
364 ToolBar toolBar
= toolBarManager
.createControl(body
);
365 toolBar
.setLayoutData(CmsUtils
.fillWidth());
366 toolBarManager
.add(action
);
367 toolBarManager
.update(true);
368 return userViewerCmp
;
371 private class MyUserTableViewer
extends LdifUsersTable
{
372 private static final long serialVersionUID
= 2653790051461237329L;
374 private Button showSystemRoleBtn
;
376 private final User user
;
377 private final UserFilter userFilter
;
379 public MyUserTableViewer(Composite parent
, int style
, User user
) {
380 super(parent
, style
, true);
382 userFilter
= new UserFilter();
385 protected void populateStaticFilters(Composite staticFilterCmp
) {
386 staticFilterCmp
.setLayout(new GridLayout());
387 showSystemRoleBtn
= new Button(staticFilterCmp
, SWT
.CHECK
);
388 showSystemRoleBtn
.setText("Show system roles");
389 boolean showSysRole
= CurrentUser
.isInRole(NodeConstants
.ROLE_ADMIN
);
390 showSystemRoleBtn
.setSelection(showSysRole
);
391 userFilter
.setShowSystemRole(showSysRole
);
392 showSystemRoleBtn
.addSelectionListener(new SelectionAdapter() {
393 private static final long serialVersionUID
= -7033424592697691676L;
396 public void widgetSelected(SelectionEvent e
) {
397 userFilter
.setShowSystemRole(showSystemRoleBtn
.getSelection());
404 protected List
<User
> listFilteredElements(String filter
) {
405 List
<User
> users
= (List
<User
>) getFlatGroups(null);
406 List
<User
> filteredUsers
= new ArrayList
<User
>();
407 if (users
.contains(user
))
409 userFilter
.setSearchText(filter
);
410 for (User user
: users
)
411 if (userFilter
.select(null, null, user
))
412 filteredUsers
.add(user
);
413 return filteredUsers
;
417 // private void addRemoveAbility(Composite parent, TableViewer userViewer, User
419 // // Section section = sectionPart.getSection();
420 // ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
421 // ToolBar toolbar = toolBarManager.createControl(parent);
422 // final Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
423 // toolbar.setCursor(handCursor);
424 // toolbar.addDisposeListener(new DisposeListener() {
425 // private static final long serialVersionUID = 3882131405820522925L;
427 // public void widgetDisposed(DisposeEvent e) {
428 // if ((handCursor != null) && (handCursor.isDisposed() == false)) {
429 // handCursor.dispose();
434 // String tooltip = "Remove " + UserAdminUtils.getUserLocalId(user.getName()) +
435 // " from the below selected groups";
436 // Action action = new RemoveMembershipAction(userViewer, user, tooltip,
437 // SecurityAdminImages.ICON_REMOVE_DESC);
438 // toolBarManager.add(action);
439 // toolBarManager.update(true);
440 // // section.setTextClient(toolbar);
443 private class RemoveMembershipAction
extends Action
{
444 private static final long serialVersionUID
= -1337713097184522588L;
446 private final TableViewer userViewer
;
447 private final User user
;
449 RemoveMembershipAction(TableViewer userViewer
, User user
, String name
, ImageDescriptor img
) {
451 this.userViewer
= userViewer
;
457 ISelection selection
= userViewer
.getSelection();
458 if (selection
.isEmpty())
461 @SuppressWarnings("unchecked")
462 Iterator
<Group
> it
= ((IStructuredSelection
) selection
).iterator();
463 List
<Group
> groups
= new ArrayList
<Group
>();
464 while (it
.hasNext()) {
465 Group currGroup
= it
.next();
466 groups
.add(currGroup
);
469 userAdminWrapper
.beginTransactionIfNeeded();
470 for (Group group
: groups
) {
471 group
.removeMember(user
);
473 userAdminWrapper
.commitOrNotifyTransactionStateChange();
474 for (Group group
: groups
) {
475 userAdminWrapper
.notifyListeners(new UserAdminEvent(null, UserAdminEvent
.ROLE_CHANGED
, group
));
481 * Defines the table as being a potential target to add group memberships
482 * (roles) to this user
484 private class GroupDropListener
extends ViewerDropAdapter
{
485 private static final long serialVersionUID
= 2893468717831451621L;
487 private final UserAdminWrapper myUserAdminWrapper
;
488 private final User myUser
;
490 public GroupDropListener(UserAdminWrapper userAdminWrapper
, Viewer userViewer
, User user
) {
492 this.myUserAdminWrapper
= userAdminWrapper
;
497 public boolean validateDrop(Object target
, int operation
, TransferData transferType
) {
498 // Target is always OK in a list only view
499 // TODO check if not a string
500 boolean validDrop
= true;
505 public void drop(DropTargetEvent event
) {
506 String name
= (String
) event
.data
;
507 UserAdmin myUserAdmin
= myUserAdminWrapper
.getUserAdmin();
508 Role role
= myUserAdmin
.getRole(name
);
509 // TODO this check should be done before.
510 if (role
.getType() == Role
.GROUP
) {
511 // TODO check if the user is already member of this group
513 myUserAdminWrapper
.beginTransactionIfNeeded();
514 Group group
= (Group
) role
;
515 group
.addMember(myUser
);
516 userAdminWrapper
.commitOrNotifyTransactionStateChange();
517 myUserAdminWrapper
.notifyListeners(new UserAdminEvent(null, UserAdminEvent
.ROLE_CHANGED
, group
));
523 public boolean performDrop(Object data
) {
524 // userTableViewerCmp.refresh();
530 private void refreshFormTitle(User group
) {
531 // getManagedForm().getForm().setText(UserAdminUtils.getProperty(group,
532 // LdapAttrs.cn.name()));
535 /** Appends a section with a title */
536 // private Section addSection(FormToolkit tk, Composite parent, String title) {
537 // Section section = tk.createSection(parent, Section.TITLE_BAR);
538 // GridData gd = EclipseUiUtils.fillWidth();
539 // gd.verticalAlignment = PRE_TITLE_INDENT;
540 // section.setLayoutData(gd);
541 // section.setText(title);
542 // // section.getMenu().setVisible(true);
544 // Composite body = tk.createComposite(section, SWT.WRAP);
545 // body.setLayoutData(EclipseUiUtils.fillAll());
546 // section.setClient(body);