1 package org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.parts
;
3 import static org
.argeo
.cms
.auth
.UserAdminUtils
.getProperty
;
4 import static org
.argeo
.naming
.LdapAttrs
.cn
;
5 import static org
.argeo
.naming
.LdapAttrs
.givenName
;
6 import static org
.argeo
.naming
.LdapAttrs
.mail
;
7 import static org
.argeo
.naming
.LdapAttrs
.sn
;
8 import static org
.argeo
.naming
.LdapAttrs
.uid
;
10 import java
.util
.ArrayList
;
11 import java
.util
.Iterator
;
12 import java
.util
.List
;
14 import org
.argeo
.api
.NodeConstants
;
15 import org
.argeo
.cms
.ArgeoNames
;
16 import org
.argeo
.cms
.auth
.CurrentUser
;
17 import org
.argeo
.cms
.ui
.workbench
.CmsWorkbenchStyles
;
18 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.SecurityAdminImages
;
19 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.UserAdminWrapper
;
20 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.parts
.UserEditor
.GroupChangeListener
;
21 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.parts
.UserEditor
.MainInfoListener
;
22 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.providers
.CommonNameLP
;
23 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.providers
.DomainNameLP
;
24 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.providers
.RoleIconLP
;
25 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.providers
.UserFilter
;
26 import org
.argeo
.cms
.ui
.workbench
.internal
.useradmin
.providers
.UserTableDefaultDClickListener
;
27 import org
.argeo
.cms
.ui
.util
.CmsUiUtils
;
28 import org
.argeo
.cms
.auth
.UserAdminUtils
;
29 import org
.argeo
.eclipse
.ui
.ColumnDefinition
;
30 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
31 import org
.argeo
.eclipse
.ui
.parts
.LdifUsersTable
;
32 import org
.argeo
.naming
.LdapAttrs
;
33 import org
.eclipse
.jface
.action
.Action
;
34 import org
.eclipse
.jface
.action
.ToolBarManager
;
35 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
36 import org
.eclipse
.jface
.dialogs
.TrayDialog
;
37 import org
.eclipse
.jface
.resource
.ImageDescriptor
;
38 import org
.eclipse
.jface
.viewers
.ISelection
;
39 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
40 import org
.eclipse
.jface
.viewers
.TableViewer
;
41 import org
.eclipse
.jface
.viewers
.Viewer
;
42 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
43 import org
.eclipse
.swt
.SWT
;
44 import org
.eclipse
.swt
.dnd
.DND
;
45 import org
.eclipse
.swt
.dnd
.DropTargetEvent
;
46 import org
.eclipse
.swt
.dnd
.TextTransfer
;
47 import org
.eclipse
.swt
.dnd
.Transfer
;
48 import org
.eclipse
.swt
.dnd
.TransferData
;
49 import org
.eclipse
.swt
.events
.DisposeEvent
;
50 import org
.eclipse
.swt
.events
.DisposeListener
;
51 import org
.eclipse
.swt
.events
.ModifyEvent
;
52 import org
.eclipse
.swt
.events
.ModifyListener
;
53 import org
.eclipse
.swt
.events
.SelectionAdapter
;
54 import org
.eclipse
.swt
.events
.SelectionEvent
;
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
.Button
;
59 import org
.eclipse
.swt
.widgets
.Composite
;
60 import org
.eclipse
.swt
.widgets
.Control
;
61 import org
.eclipse
.swt
.widgets
.Display
;
62 import org
.eclipse
.swt
.widgets
.Label
;
63 import org
.eclipse
.swt
.widgets
.Link
;
64 import org
.eclipse
.swt
.widgets
.Shell
;
65 import org
.eclipse
.swt
.widgets
.Text
;
66 import org
.eclipse
.swt
.widgets
.ToolBar
;
67 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
68 import org
.eclipse
.ui
.forms
.IManagedForm
;
69 import org
.eclipse
.ui
.forms
.SectionPart
;
70 import org
.eclipse
.ui
.forms
.editor
.FormEditor
;
71 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
72 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
73 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
74 import org
.eclipse
.ui
.forms
.widgets
.Section
;
75 import org
.osgi
.service
.useradmin
.Group
;
76 import org
.osgi
.service
.useradmin
.Role
;
77 import org
.osgi
.service
.useradmin
.User
;
78 import org
.osgi
.service
.useradmin
.UserAdmin
;
79 import org
.osgi
.service
.useradmin
.UserAdminEvent
;
81 /** Display/edit the properties of a given user */
82 public class UserMainPage
extends FormPage
implements ArgeoNames
{
83 final static String ID
= "UserEditor.mainPage";
85 private final UserEditor editor
;
86 private UserAdminWrapper userAdminWrapper
;
88 // Local configuration
89 private final int PRE_TITLE_INDENT
= 10;
91 public UserMainPage(FormEditor editor
, UserAdminWrapper userAdminWrapper
) {
92 super(editor
, ID
, "Main");
93 this.editor
= (UserEditor
) editor
;
94 this.userAdminWrapper
= userAdminWrapper
;
97 protected void createFormContent(final IManagedForm mf
) {
98 ScrolledForm form
= mf
.getForm();
99 Composite body
= form
.getBody();
100 GridLayout mainLayout
= new GridLayout();
101 // mainLayout.marginRight = 10;
102 body
.setLayout(mainLayout
);
103 User user
= editor
.getDisplayedUser();
104 appendOverviewPart(body
, user
);
105 // Remove to ability to force the password for his own user. The user
106 // must then use the change pwd feature
107 appendMemberOfPart(body
, user
);
110 /** Creates the general section */
111 private void appendOverviewPart(final Composite parent
, final User user
) {
112 FormToolkit tk
= getManagedForm().getToolkit();
114 Section section
= tk
.createSection(parent
, SWT
.NO_FOCUS
);
115 GridData gd
= EclipseUiUtils
.fillWidth();
116 // gd.verticalAlignment = PRE_TITLE_INDENT;
117 section
.setLayoutData(gd
);
118 Composite body
= tk
.createComposite(section
, SWT
.WRAP
);
119 body
.setLayoutData(EclipseUiUtils
.fillAll());
120 section
.setClient(body
);
121 // body.setLayout(new GridLayout(6, false));
122 body
.setLayout(new GridLayout(2, false));
124 Text commonName
= createReadOnlyLT(tk
, body
, "Name", getProperty(user
, cn
));
125 Text distinguishedName
= createReadOnlyLT(tk
, body
, "Login", getProperty(user
, uid
));
126 Text firstName
= createLT(tk
, body
, "First name", getProperty(user
, givenName
));
127 Text lastName
= createLT(tk
, body
, "Last name", getProperty(user
, sn
));
128 Text email
= createLT(tk
, body
, "Email", getProperty(user
, mail
));
130 Link resetPwdLk
= new Link(body
, SWT
.NONE
);
131 if (!UserAdminUtils
.isCurrentUser(user
)) {
132 resetPwdLk
.setText("<a>Reset password</a>");
134 resetPwdLk
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false, 2, 1));
136 // create form part (controller)
137 AbstractFormPart part
= new SectionPart((Section
) body
.getParent()) {
138 private MainInfoListener listener
;
141 public void initialize(IManagedForm form
) {
142 super.initialize(form
);
143 listener
= editor
.new MainInfoListener(parent
.getDisplay(), this);
144 userAdminWrapper
.addListener(listener
);
148 public void dispose() {
149 userAdminWrapper
.removeListener(listener
);
153 @SuppressWarnings("unchecked")
154 public void commit(boolean onSave
) {
155 // TODO Sanity checks (mail validity...)
156 user
.getProperties().put(LdapAttrs
.givenName
.name(), firstName
.getText());
157 user
.getProperties().put(LdapAttrs
.sn
.name(), lastName
.getText());
158 user
.getProperties().put(LdapAttrs
.cn
.name(), commonName
.getText());
159 user
.getProperties().put(LdapAttrs
.mail
.name(), email
.getText());
160 super.commit(onSave
);
164 public void refresh() {
165 distinguishedName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.uid
.name()));
166 commonName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.cn
.name()));
167 firstName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.givenName
.name()));
168 lastName
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.sn
.name()));
169 email
.setText(UserAdminUtils
.getProperty(user
, LdapAttrs
.mail
.name()));
170 refreshFormTitle(user
);
175 // Improve this: automatically generate CN when first or last name
177 ModifyListener cnML
= new ModifyListener() {
178 private static final long serialVersionUID
= 4298649222869835486L;
181 public void modifyText(ModifyEvent event
) {
182 String first
= firstName
.getText();
183 String last
= lastName
.getText();
184 String cn
= first
.trim() + " " + last
.trim() + " ";
186 commonName
.setText(cn
);
187 // getManagedForm().getForm().setText(cn);
188 editor
.updateEditorTitle(cn
);
191 firstName
.addModifyListener(cnML
);
192 lastName
.addModifyListener(cnML
);
194 ModifyListener defaultListener
= editor
.new FormPartML(part
);
195 firstName
.addModifyListener(defaultListener
);
196 lastName
.addModifyListener(defaultListener
);
197 email
.addModifyListener(defaultListener
);
199 if (!UserAdminUtils
.isCurrentUser(user
))
200 resetPwdLk
.addSelectionListener(new SelectionAdapter() {
201 private static final long serialVersionUID
= 5881800534589073787L;
204 public void widgetSelected(SelectionEvent e
) {
205 new ChangePasswordDialog(tk
, user
, "Reset password").open();
209 getManagedForm().addPart(part
);
212 private class ChangePasswordDialog
extends TrayDialog
{
213 private static final long serialVersionUID
= 2843538207460082349L;
216 private Text password1
;
217 private Text password2
;
218 private String title
;
219 private FormToolkit tk
;
221 public ChangePasswordDialog(FormToolkit tk
, User user
, String title
) {
222 super(Display
.getDefault().getActiveShell());
228 protected Control
createDialogArea(Composite parent
) {
229 Composite dialogarea
= (Composite
) super.createDialogArea(parent
);
230 dialogarea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
231 Composite body
= new Composite(dialogarea
, SWT
.NO_FOCUS
);
232 body
.setLayoutData(EclipseUiUtils
.fillAll());
233 GridLayout layout
= new GridLayout(2, false);
234 body
.setLayout(layout
);
236 password1
= createLP(tk
, body
, "New password", "");
237 password2
= createLP(tk
, body
, "Repeat password", "");
242 @SuppressWarnings("unchecked")
244 protected void okPressed() {
247 if (password1
.getText().equals(""))
248 msg
= "Password cannot be empty";
249 else if (password1
.getText().equals(password2
.getText())) {
250 char[] newPassword
= password1
.getText().toCharArray();
251 // userAdminWrapper.beginTransactionIfNeeded();
252 userAdminWrapper
.beginTransactionIfNeeded();
253 user
.getCredentials().put(null, newPassword
);
254 userAdminWrapper
.commitOrNotifyTransactionStateChange();
257 msg
= "Passwords are not equals";
260 if (EclipseUiUtils
.notEmpty(msg
))
261 MessageDialog
.openError(getParentShell(), "Cannot reset pasword", msg
);
264 protected void configureShell(Shell shell
) {
265 super.configureShell(shell
);
266 shell
.setText(title
);
270 private LdifUsersTable
appendMemberOfPart(final Composite parent
, User user
) {
271 FormToolkit tk
= getManagedForm().getToolkit();
272 Section section
= addSection(tk
, parent
, "Roles");
273 Composite body
= (Composite
) section
.getClient();
274 body
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
276 // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN);
279 List
<ColumnDefinition
> columnDefs
= new ArrayList
<ColumnDefinition
>();
280 columnDefs
.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
281 columnDefs
.add(new ColumnDefinition(new CommonNameLP(), "Name", 150));
282 columnDefs
.add(new ColumnDefinition(new DomainNameLP(), "Domain", 100));
283 // Only show technical DN to administrators
285 // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name",
288 // Create and configure the table
289 final LdifUsersTable userViewerCmp
= new MyUserTableViewer(body
, SWT
.MULTI
| SWT
.H_SCROLL
| SWT
.V_SCROLL
, user
);
291 userViewerCmp
.setColumnDefinitions(columnDefs
);
293 // userViewerCmp.populateWithStaticFilters(false, false);
295 userViewerCmp
.populate(true, false);
296 GridData gd
= EclipseUiUtils
.fillAll();
298 userViewerCmp
.setLayoutData(gd
);
301 TableViewer userViewer
= userViewerCmp
.getTableViewer();
302 userViewer
.addDoubleClickListener(new UserTableDefaultDClickListener());
303 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
304 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
305 GroupDropListener dropL
= new GroupDropListener(userAdminWrapper
, userViewer
, user
);
306 userViewer
.addDropSupport(operations
, tt
, dropL
);
308 SectionPart part
= new SectionPart((Section
) body
.getParent()) {
310 private GroupChangeListener listener
;
313 public void initialize(IManagedForm form
) {
314 super.initialize(form
);
315 listener
= editor
.new GroupChangeListener(parent
.getDisplay(), this);
316 userAdminWrapper
.addListener(listener
);
319 public void commit(boolean onSave
) {
320 super.commit(onSave
);
324 public void dispose() {
325 userAdminWrapper
.removeListener(listener
);
330 public void refresh() {
331 userViewerCmp
.refresh();
335 getManagedForm().addPart(part
);
336 addRemoveAbitily(part
, userViewer
, user
);
337 return userViewerCmp
;
340 private class MyUserTableViewer
extends LdifUsersTable
{
341 private static final long serialVersionUID
= 2653790051461237329L;
343 private Button showSystemRoleBtn
;
345 private final User user
;
346 private final UserFilter userFilter
;
348 public MyUserTableViewer(Composite parent
, int style
, User user
) {
349 super(parent
, style
, true);
351 userFilter
= new UserFilter();
354 protected void populateStaticFilters(Composite staticFilterCmp
) {
355 staticFilterCmp
.setLayout(new GridLayout());
356 showSystemRoleBtn
= new Button(staticFilterCmp
, SWT
.CHECK
);
357 showSystemRoleBtn
.setText("Show system roles");
358 boolean showSysRole
= CurrentUser
.isInRole(NodeConstants
.ROLE_ADMIN
);
359 showSystemRoleBtn
.setSelection(showSysRole
);
360 userFilter
.setShowSystemRole(showSysRole
);
361 showSystemRoleBtn
.addSelectionListener(new SelectionAdapter() {
362 private static final long serialVersionUID
= -7033424592697691676L;
365 public void widgetSelected(SelectionEvent e
) {
366 userFilter
.setShowSystemRole(showSystemRoleBtn
.getSelection());
373 protected List
<User
> listFilteredElements(String filter
) {
374 List
<User
> users
= (List
<User
>) editor
.getFlatGroups(null);
375 List
<User
> filteredUsers
= new ArrayList
<User
>();
376 if (users
.contains(user
))
378 userFilter
.setSearchText(filter
);
379 for (User user
: users
)
380 if (userFilter
.select(null, null, user
))
381 filteredUsers
.add(user
);
382 return filteredUsers
;
386 private void addRemoveAbitily(SectionPart sectionPart
, TableViewer userViewer
, User user
) {
387 Section section
= sectionPart
.getSection();
388 ToolBarManager toolBarManager
= new ToolBarManager(SWT
.FLAT
);
389 ToolBar toolbar
= toolBarManager
.createControl(section
);
390 final Cursor handCursor
= new Cursor(section
.getDisplay(), SWT
.CURSOR_HAND
);
391 toolbar
.setCursor(handCursor
);
392 toolbar
.addDisposeListener(new DisposeListener() {
393 private static final long serialVersionUID
= 3882131405820522925L;
395 public void widgetDisposed(DisposeEvent e
) {
396 if ((handCursor
!= null) && (handCursor
.isDisposed() == false)) {
397 handCursor
.dispose();
402 String tooltip
= "Remove " + UserAdminUtils
.getUserLocalId(user
.getName()) + " from the below selected groups";
403 Action action
= new RemoveMembershipAction(userViewer
, user
, tooltip
, SecurityAdminImages
.ICON_REMOVE_DESC
);
404 toolBarManager
.add(action
);
405 toolBarManager
.update(true);
406 section
.setTextClient(toolbar
);
409 private class RemoveMembershipAction
extends Action
{
410 private static final long serialVersionUID
= -1337713097184522588L;
412 private final TableViewer userViewer
;
413 private final User user
;
415 RemoveMembershipAction(TableViewer userViewer
, User user
, String name
, ImageDescriptor img
) {
417 this.userViewer
= userViewer
;
423 ISelection selection
= userViewer
.getSelection();
424 if (selection
.isEmpty())
427 @SuppressWarnings("unchecked")
428 Iterator
<Group
> it
= ((IStructuredSelection
) selection
).iterator();
429 List
<Group
> groups
= new ArrayList
<Group
>();
430 while (it
.hasNext()) {
431 Group currGroup
= it
.next();
432 groups
.add(currGroup
);
435 userAdminWrapper
.beginTransactionIfNeeded();
436 for (Group group
: groups
) {
437 group
.removeMember(user
);
439 userAdminWrapper
.commitOrNotifyTransactionStateChange();
440 for (Group group
: groups
) {
441 userAdminWrapper
.notifyListeners(new UserAdminEvent(null, UserAdminEvent
.ROLE_CHANGED
, group
));
447 * Defines the table as being a potential target to add group memberships
448 * (roles) to this user
450 private class GroupDropListener
extends ViewerDropAdapter
{
451 private static final long serialVersionUID
= 2893468717831451621L;
453 private final UserAdminWrapper myUserAdminWrapper
;
454 private final User myUser
;
456 public GroupDropListener(UserAdminWrapper userAdminWrapper
, Viewer userViewer
, User user
) {
458 this.myUserAdminWrapper
= userAdminWrapper
;
463 public boolean validateDrop(Object target
, int operation
, TransferData transferType
) {
464 // Target is always OK in a list only view
465 // TODO check if not a string
466 boolean validDrop
= true;
471 public void drop(DropTargetEvent event
) {
472 String name
= (String
) event
.data
;
473 UserAdmin myUserAdmin
= myUserAdminWrapper
.getUserAdmin();
474 Role role
= myUserAdmin
.getRole(name
);
475 // TODO this check should be done before.
476 if (role
.getType() == Role
.GROUP
) {
477 // TODO check if the user is already member of this group
479 myUserAdminWrapper
.beginTransactionIfNeeded();
480 Group group
= (Group
) role
;
481 group
.addMember(myUser
);
482 userAdminWrapper
.commitOrNotifyTransactionStateChange();
483 myUserAdminWrapper
.notifyListeners(new UserAdminEvent(null, UserAdminEvent
.ROLE_CHANGED
, group
));
489 public boolean performDrop(Object data
) {
490 // userTableViewerCmp.refresh();
496 private void refreshFormTitle(User group
) {
497 // getManagedForm().getForm().setText(UserAdminUtils.getProperty(group,
498 // LdapAttrs.cn.name()));
501 /** Appends a section with a title */
502 private Section
addSection(FormToolkit tk
, Composite parent
, String title
) {
503 Section section
= tk
.createSection(parent
, Section
.TITLE_BAR
);
504 GridData gd
= EclipseUiUtils
.fillWidth();
505 gd
.verticalAlignment
= PRE_TITLE_INDENT
;
506 section
.setLayoutData(gd
);
507 section
.setText(title
);
508 // section.getMenu().setVisible(true);
510 Composite body
= tk
.createComposite(section
, SWT
.WRAP
);
511 body
.setLayoutData(EclipseUiUtils
.fillAll());
512 section
.setClient(body
);
517 /** Creates label and multiline text. */
518 Text
createLMT(FormToolkit toolkit
, Composite body
, String label
, String value
) {
519 Label lbl
= toolkit
.createLabel(body
, label
);
520 lbl
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.CENTER
, false, false));
521 Text text
= toolkit
.createText(body
, value
, SWT
.BORDER
| SWT
.MULTI
);
522 text
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, true));
526 /** Creates label and password. */
527 Text
createLP(FormToolkit toolkit
, Composite body
, String label
, String value
) {
528 Label lbl
= toolkit
.createLabel(body
, label
);
529 lbl
.setLayoutData(new GridData(SWT
.LEAD
, SWT
.CENTER
, false, false));
530 Text text
= toolkit
.createText(body
, value
, SWT
.BORDER
| SWT
.PASSWORD
);
531 text
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
535 /** Creates label and text. */
536 Text
createLT(FormToolkit toolkit
, Composite parent
, String label
, String value
) {
537 Label lbl
= toolkit
.createLabel(parent
, label
);
538 lbl
.setLayoutData(new GridData(SWT
.LEAD
, SWT
.CENTER
, false, false));
539 lbl
.setFont(EclipseUiUtils
.getBoldFont(parent
));
540 Text text
= toolkit
.createText(parent
, value
, SWT
.BORDER
);
541 text
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
542 CmsUiUtils
.style(text
, CmsWorkbenchStyles
.WORKBENCH_FORM_TEXT
);
546 Text
createReadOnlyLT(FormToolkit toolkit
, Composite parent
, String label
, String value
) {
547 Label lbl
= toolkit
.createLabel(parent
, label
);
548 lbl
.setLayoutData(new GridData(SWT
.LEAD
, SWT
.CENTER
, false, false));
549 lbl
.setFont(EclipseUiUtils
.getBoldFont(parent
));
550 Text text
= toolkit
.createText(parent
, value
, SWT
.NONE
);
551 text
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
552 text
.setEditable(false);
553 CmsUiUtils
.style(text
, CmsWorkbenchStyles
.WORKBENCH_FORM_TEXT
);