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
.security
.ui
.admin
.internal
.parts
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Iterator
;
20 import java
.util
.List
;
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
;
76 /** Display/edit the properties of a given user */
77 public class UserMainPage
extends FormPage
implements ArgeoNames
{
78 final static String ID
= "UserEditor.mainPage";
80 private final UserEditor editor
;
81 private UserAdminWrapper userAdminWrapper
;
83 // Local configuration
84 private final int PRE_TITLE_INDENT
= 10;
86 public UserMainPage(FormEditor editor
, UserAdminWrapper userAdminWrapper
) {
87 super(editor
, ID
, "Main");
88 this.editor
= (UserEditor
) editor
;
89 this.userAdminWrapper
= userAdminWrapper
;
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
);
106 /** Creates the general section */
107 private void appendOverviewPart(Composite parent
, final User user
) {
108 FormToolkit tk
= getManagedForm().getToolkit();
110 Section section
= addSection(tk
, parent
, "Main information");
111 Composite body
= (Composite
) section
.getClient();
112 body
.setLayout(new GridLayout(2, false));
114 final Text distinguishedName
= createLT(tk
, body
, "User Name",
115 UiAdminUtils
.getProperty(user
, UserAdminConstants
.KEY_UID
));
116 distinguishedName
.setEnabled(false);
118 final Text commonName
= createLT(tk
, body
, "Common Name",
119 UiAdminUtils
.getProperty(user
, UserAdminConstants
.KEY_CN
));
120 commonName
.setEnabled(false);
122 final Text firstName
= createLT(tk
, body
, "First name",
124 .getProperty(user
, UserAdminConstants
.KEY_FIRSTNAME
));
126 final Text lastName
= createLT(tk
, body
, "Last name",
127 UiAdminUtils
.getProperty(user
, UserAdminConstants
.KEY_LASTNAME
));
129 final Text email
= createLT(tk
, body
, "Email",
130 UiAdminUtils
.getProperty(user
, UserAdminConstants
.KEY_MAIL
));
132 // create form part (controller)
133 AbstractFormPart part
= new SectionPart((Section
) body
.getParent()) {
134 private MainInfoListener listener
;
137 public void initialize(IManagedForm form
) {
138 super.initialize(form
);
139 listener
= editor
.new MainInfoListener(this);
140 userAdminWrapper
.addListener(listener
);
144 public void dispose() {
145 userAdminWrapper
.removeListener(listener
);
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
,
155 editor
.setProperty(UserAdminConstants
.KEY_CN
,
156 commonName
.getText());
157 // TODO check mail validity
158 editor
.setProperty(UserAdminConstants
.KEY_MAIL
, email
.getText());
160 // Enable common name ?
161 // editor.setProperty(UserAdminConstants.KEY_CN,
163 super.commit(onSave
);
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
);
183 // Improve this: automatically generate CN when first or last name
185 ModifyListener cnML
= new ModifyListener() {
186 private static final long serialVersionUID
= 4298649222869835486L;
189 public void modifyText(ModifyEvent event
) {
190 String first
= firstName
.getText();
191 String last
= lastName
.getText();
192 String cn
= first
.trim() + " " + last
.trim() + " ";
194 commonName
.setText(cn
);
195 getManagedForm().getForm().setText(cn
);
196 editor
.updateEditorTitle(cn
);
199 firstName
.addModifyListener(cnML
);
200 lastName
.addModifyListener(cnML
);
202 ModifyListener defaultListener
= editor
.new FormPartML(part
);
203 firstName
.addModifyListener(defaultListener
);
204 lastName
.addModifyListener(defaultListener
);
205 email
.addModifyListener(defaultListener
);
206 getManagedForm().addPart(part
);
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));
216 // add widgets (view)
217 final Text password1
= createLP(tk
, body
, "New password", "");
218 final Text password2
= createLP(tk
, body
, "Repeat password", "");
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
);
234 password1
.setText("");
235 password2
.setText("");
236 throw new ArgeoException("Passwords are not equals");
241 ModifyListener defaultListener
= editor
.new FormPartML(part
);
242 password1
.addModifyListener(defaultListener
);
243 password2
.addModifyListener(defaultListener
);
244 getManagedForm().addPart(part
);
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());
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",
258 columnDefs
.add(new ColumnDefinition(new UserNameLP(),
259 "Distinguished Name", 300));
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
);
266 userViewerCmp
.setColumnDefinitions(columnDefs
);
267 userViewerCmp
.populate(true, false);
268 GridData gd
= EclipseUiUtils
.fillAll();
270 userViewerCmp
.setLayoutData(gd
);
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
,
279 userViewer
.addDropSupport(operations
, tt
, dropL
);
281 SectionPart part
= new SectionPart((Section
) body
.getParent()) {
283 private GroupChangeListener listener
;
286 public void initialize(IManagedForm form
) {
287 super.initialize(form
);
288 listener
= editor
.new GroupChangeListener(this);
289 userAdminWrapper
.addListener(listener
);
292 public void commit(boolean onSave
) {
293 super.commit(onSave
);
297 public void dispose() {
298 userAdminWrapper
.removeListener(listener
);
303 public void refresh() {
304 userViewerCmp
.refresh();
308 getManagedForm().addPart(part
);
309 addRemoveAbitily(part
, userViewer
, user
);
310 return userViewerCmp
;
313 private class MyUserTableViewer
extends UserTableViewer
{
314 private static final long serialVersionUID
= 8467999509931900367L;
316 private final User user
;
318 public MyUserTableViewer(Composite parent
, int style
,
319 UserAdmin userAdmin
, User user
) {
320 super(parent
, style
, userAdmin
, true);
325 protected List
<User
> listFilteredElements(String filter
) {
326 List
<User
> users
= (List
<User
>) editor
.getFlatGroups(null);
327 if (users
.contains(user
))
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(),
340 toolbar
.setCursor(handCursor
);
341 toolbar
.addDisposeListener(new DisposeListener() {
342 private static final long serialVersionUID
= 3882131405820522925L;
344 public void widgetDisposed(DisposeEvent e
) {
345 if ((handCursor
!= null) && (handCursor
.isDisposed() == false)) {
346 handCursor
.dispose();
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
);
358 private class RemoveMembershipAction
extends Action
{
359 private static final long serialVersionUID
= -1337713097184522588L;
361 private final TableViewer userViewer
;
362 private final User user
;
364 RemoveMembershipAction(TableViewer userViewer
, User user
, String name
,
365 ImageDescriptor img
) {
367 this.userViewer
= userViewer
;
373 ISelection selection
= userViewer
.getSelection();
374 if (selection
.isEmpty())
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
);
388 // if (!MessageDialog.openQuestion(
389 // HandlerUtil.getActiveShell(event),
391 // "Are you sure that you want to delete these users?\n"
392 // + builder.substring(0, builder.length() - 2)))
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
));
406 * Defines the table as being a potential target to add group memberships
407 * (roles) to this user
409 private class GroupDropListener
extends ViewerDropAdapter
{
410 private static final long serialVersionUID
= 2893468717831451621L;
412 private final UserAdminWrapper myUserAdminWrapper
;
413 private final User myUser
;
415 public GroupDropListener(UserAdminWrapper userAdminWrapper
,
416 Viewer userViewer
, User user
) {
418 this.myUserAdminWrapper
= userAdminWrapper
;
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;
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
));
449 public boolean performDrop(Object data
) {
450 // userTableViewerCmp.refresh();
456 private void refreshFormTitle(User group
) {
457 getManagedForm().getForm().setText(
458 UiAdminUtils
.getProperty(group
, UserAdminConstants
.KEY_CN
));
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);
470 Composite body
= tk
.createComposite(section
, SWT
.WRAP
);
471 body
.setLayoutData(EclipseUiUtils
.fillAll());
472 section
.setClient(body
);
477 /** Creates label and multiline text. */
478 Text
createLMT(FormToolkit toolkit
, Composite body
, String label
,
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));
487 /** Creates label and password. */
488 Text
createLP(FormToolkit toolkit
, Composite body
, String label
,
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));
497 /** Creates label and text. */
498 Text
createLT(FormToolkit toolkit
, Composite body
, String label
,
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));