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
.ui
.workbench
.internal
.useradmin
.parts
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Iterator
;
20 import java
.util
.List
;
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
;
82 /** Display/edit the properties of a given user */
83 public class UserMainPage
extends FormPage
implements ArgeoNames
{
84 final static String ID
= "UserEditor.mainPage";
86 private final UserEditor editor
;
87 private UserAdminWrapper userAdminWrapper
;
89 // Local configuration
90 private final int PRE_TITLE_INDENT
= 10;
92 public UserMainPage(FormEditor editor
, UserAdminWrapper userAdminWrapper
) {
93 super(editor
, ID
, "Main");
94 this.editor
= (UserEditor
) editor
;
95 this.userAdminWrapper
= userAdminWrapper
;
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
);
113 /** Creates the general section */
114 private void appendOverviewPart(final Composite parent
, final User user
) {
115 FormToolkit tk
= getManagedForm().getToolkit();
117 Section section
= addSection(tk
, parent
, "Main information");
118 Composite body
= (Composite
) section
.getClient();
119 body
.setLayout(new GridLayout(2, false));
121 final Text distinguishedName
= createLT(tk
, body
, "User Name",
122 UserAdminUtils
.getProperty(user
, LdapAttrs
.uid
.name()));
123 distinguishedName
.setEnabled(false);
125 final Text commonName
= createLT(tk
, body
, "Common Name",
126 UserAdminUtils
.getProperty(user
, LdapAttrs
.cn
.name()));
127 commonName
.setEnabled(false);
129 final Text firstName
= createLT(tk
, body
, "First name",
130 UserAdminUtils
.getProperty(user
, LdapAttrs
.givenName
.name()));
132 final Text lastName
= createLT(tk
, body
, "Last name",
133 UserAdminUtils
.getProperty(user
, LdapAttrs
.sn
.name()));
135 final Text email
= createLT(tk
, body
, "Email",
136 UserAdminUtils
.getProperty(user
, LdapAttrs
.mail
.name()));
138 // create form part (controller)
139 AbstractFormPart part
= new SectionPart((Section
) body
.getParent()) {
140 private MainInfoListener listener
;
143 public void initialize(IManagedForm form
) {
144 super.initialize(form
);
145 listener
= editor
.new MainInfoListener(parent
.getDisplay(),
147 userAdminWrapper
.addListener(listener
);
151 public void dispose() {
152 userAdminWrapper
.removeListener(listener
);
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(),
163 user
.getProperties().put(LdapAttrs
.cn
.name(),
164 commonName
.getText());
166 .put(LdapAttrs
.mail
.name(), email
.getText());
167 super.commit(onSave
);
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
);
187 // Improve this: automatically generate CN when first or last name
189 ModifyListener cnML
= new ModifyListener() {
190 private static final long serialVersionUID
= 4298649222869835486L;
193 public void modifyText(ModifyEvent event
) {
194 String first
= firstName
.getText();
195 String last
= lastName
.getText();
196 String cn
= first
.trim() + " " + last
.trim() + " ";
198 commonName
.setText(cn
);
199 getManagedForm().getForm().setText(cn
);
200 editor
.updateEditorTitle(cn
);
203 firstName
.addModifyListener(cnML
);
204 lastName
.addModifyListener(cnML
);
206 ModifyListener defaultListener
= editor
.new FormPartML(part
);
207 firstName
.addModifyListener(defaultListener
);
208 lastName
.addModifyListener(defaultListener
);
209 email
.addModifyListener(defaultListener
);
210 getManagedForm().addPart(part
);
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));
220 // add widgets (view)
221 final Text password1
= createLP(tk
, body
, "New password", "");
222 final Text password2
= createLP(tk
, body
, "Repeat password", "");
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
);
238 password1
.setText("");
239 password2
.setText("");
240 throw new CmsException("Passwords are not equals");
245 ModifyListener defaultListener
= editor
.new FormPartML(part
);
246 password1
.addModifyListener(defaultListener
);
247 password2
.addModifyListener(defaultListener
);
248 getManagedForm().addPart(part
);
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());
257 boolean isAdmin
= UserAdminUtils
.isUserInRole(NodeConstants
.ROLE_ADMIN
);
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",
264 columnDefs
.add(new ColumnDefinition(new DomainNameLP(), "Domain Name",
266 // Only show technical DN to administrators
268 columnDefs
.add(new ColumnDefinition(new UserNameLP(),
269 "Distinguished Name", 120));
271 // Create and configure the table
272 final LdifUsersTable userViewerCmp
= new MyUserTableViewer(body
,
273 SWT
.MULTI
| SWT
.H_SCROLL
| SWT
.V_SCROLL
, user
);
275 userViewerCmp
.setColumnDefinitions(columnDefs
);
277 userViewerCmp
.populateWithStaticFilters(false, false);
279 userViewerCmp
.populate(true, false);
280 GridData gd
= EclipseUiUtils
.fillAll();
282 userViewerCmp
.setLayoutData(gd
);
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
,
291 userViewer
.addDropSupport(operations
, tt
, dropL
);
293 SectionPart part
= new SectionPart((Section
) body
.getParent()) {
295 private GroupChangeListener listener
;
298 public void initialize(IManagedForm form
) {
299 super.initialize(form
);
300 listener
= editor
.new GroupChangeListener(parent
.getDisplay(),
302 userAdminWrapper
.addListener(listener
);
305 public void commit(boolean onSave
) {
306 super.commit(onSave
);
310 public void dispose() {
311 userAdminWrapper
.removeListener(listener
);
316 public void refresh() {
317 userViewerCmp
.refresh();
321 getManagedForm().addPart(part
);
322 addRemoveAbitily(part
, userViewer
, user
);
323 return userViewerCmp
;
326 private class MyUserTableViewer
extends LdifUsersTable
{
327 private static final long serialVersionUID
= 2653790051461237329L;
329 private Button showSystemRoleBtn
;
331 private final User user
;
332 private final UserFilter userFilter
;
334 public MyUserTableViewer(Composite parent
, int style
, User user
) {
335 super(parent
, style
, true);
337 userFilter
= new UserFilter();
338 userFilter
.setShowSystemRole(false);
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;
349 public void widgetSelected(SelectionEvent e
) {
350 userFilter
.setShowSystemRole(showSystemRoleBtn
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
))
363 userFilter
.setSearchText(filter
);
364 for (User user
: users
)
365 if (userFilter
.select(null, null, user
))
366 filteredUsers
.add(user
);
367 return filteredUsers
;
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(),
378 toolbar
.setCursor(handCursor
);
379 toolbar
.addDisposeListener(new DisposeListener() {
380 private static final long serialVersionUID
= 3882131405820522925L;
382 public void widgetDisposed(DisposeEvent e
) {
383 if ((handCursor
!= null) && (handCursor
.isDisposed() == false)) {
384 handCursor
.dispose();
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
);
398 private class RemoveMembershipAction
extends Action
{
399 private static final long serialVersionUID
= -1337713097184522588L;
401 private final TableViewer userViewer
;
402 private final User user
;
404 RemoveMembershipAction(TableViewer userViewer
, User user
, String name
,
405 ImageDescriptor img
) {
407 this.userViewer
= userViewer
;
413 ISelection selection
= userViewer
.getSelection();
414 if (selection
.isEmpty())
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
);
425 userAdminWrapper
.beginTransactionIfNeeded();
426 for (Group group
: groups
) {
427 group
.removeMember(user
);
429 userAdminWrapper
.commitOrNotifyTransactionStateChange();
430 for (Group group
: groups
) {
431 userAdminWrapper
.notifyListeners(new UserAdminEvent(null,
432 UserAdminEvent
.ROLE_CHANGED
, group
));
438 * Defines the table as being a potential target to add group memberships
439 * (roles) to this user
441 private class GroupDropListener
extends ViewerDropAdapter
{
442 private static final long serialVersionUID
= 2893468717831451621L;
444 private final UserAdminWrapper myUserAdminWrapper
;
445 private final User myUser
;
447 public GroupDropListener(UserAdminWrapper userAdminWrapper
,
448 Viewer userViewer
, User user
) {
450 this.myUserAdminWrapper
= userAdminWrapper
;
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;
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
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
));
483 public boolean performDrop(Object data
) {
484 // userTableViewerCmp.refresh();
490 private void refreshFormTitle(User group
) {
491 getManagedForm().getForm().setText(
492 UserAdminUtils
.getProperty(group
, LdapAttrs
.cn
.name()));
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);
504 Composite body
= tk
.createComposite(section
, SWT
.WRAP
);
505 body
.setLayoutData(EclipseUiUtils
.fillAll());
506 section
.setClient(body
);
511 /** Creates label and multiline text. */
512 Text
createLMT(FormToolkit toolkit
, Composite body
, String label
,
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));
521 /** Creates label and password. */
522 Text
createLP(FormToolkit toolkit
, Composite body
, String label
,
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));
531 /** Creates label and text. */
532 Text
createLT(FormToolkit toolkit
, Composite body
, String label
,
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));