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
.eclipse
.ui
.ColumnDefinition
;
23 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
24 import org
.argeo
.eclipse
.ui
.parts
.LdifUsersTable
;
25 import org
.argeo
.jcr
.ArgeoNames
;
26 import org
.argeo
.osgi
.useradmin
.LdifName
;
27 import org
.argeo
.security
.ui
.admin
.SecurityAdminImages
;
28 import org
.argeo
.security
.ui
.admin
.internal
.UiAdminUtils
;
29 import org
.argeo
.security
.ui
.admin
.internal
.UserAdminWrapper
;
30 import org
.argeo
.security
.ui
.admin
.internal
.parts
.UserEditor
.GroupChangeListener
;
31 import org
.argeo
.security
.ui
.admin
.internal
.parts
.UserEditor
.MainInfoListener
;
32 import org
.argeo
.security
.ui
.admin
.internal
.providers
.CommonNameLP
;
33 import org
.argeo
.security
.ui
.admin
.internal
.providers
.MailLP
;
34 import org
.argeo
.security
.ui
.admin
.internal
.providers
.RoleIconLP
;
35 import org
.argeo
.security
.ui
.admin
.internal
.providers
.UserFilter
;
36 import org
.argeo
.security
.ui
.admin
.internal
.providers
.UserNameLP
;
37 import org
.argeo
.security
.ui
.admin
.internal
.providers
.UserTableDefaultDClickListener
;
38 import org
.eclipse
.jface
.action
.Action
;
39 import org
.eclipse
.jface
.action
.ToolBarManager
;
40 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
41 import org
.eclipse
.jface
.resource
.ImageDescriptor
;
42 import org
.eclipse
.jface
.viewers
.ISelection
;
43 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
44 import org
.eclipse
.jface
.viewers
.TableViewer
;
45 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
46 import org
.eclipse
.swt
.SWT
;
47 import org
.eclipse
.swt
.dnd
.DND
;
48 import org
.eclipse
.swt
.dnd
.DropTargetEvent
;
49 import org
.eclipse
.swt
.dnd
.TextTransfer
;
50 import org
.eclipse
.swt
.dnd
.Transfer
;
51 import org
.eclipse
.swt
.dnd
.TransferData
;
52 import org
.eclipse
.swt
.events
.DisposeEvent
;
53 import org
.eclipse
.swt
.events
.DisposeListener
;
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
.Shell
;
61 import org
.eclipse
.swt
.widgets
.Text
;
62 import org
.eclipse
.swt
.widgets
.ToolBar
;
63 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
64 import org
.eclipse
.ui
.forms
.IManagedForm
;
65 import org
.eclipse
.ui
.forms
.SectionPart
;
66 import org
.eclipse
.ui
.forms
.editor
.FormEditor
;
67 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
68 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
69 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
70 import org
.eclipse
.ui
.forms
.widgets
.Section
;
71 import org
.osgi
.service
.useradmin
.Group
;
72 import org
.osgi
.service
.useradmin
.Role
;
73 import org
.osgi
.service
.useradmin
.User
;
74 import org
.osgi
.service
.useradmin
.UserAdmin
;
75 import org
.osgi
.service
.useradmin
.UserAdminEvent
;
77 /** Display/edit main properties of a given group */
78 public class GroupMainPage
extends FormPage
implements ArgeoNames
{
79 final static String ID
= "GroupEditor.mainPage";
81 private final UserEditor editor
;
82 private UserAdminWrapper userAdminWrapper
;
84 // Local configuration
85 private final int PRE_TITLE_INDENT
= 10;
87 public GroupMainPage(FormEditor editor
, UserAdminWrapper userAdminWrapper
) {
88 super(editor
, ID
, "Main");
89 this.editor
= (UserEditor
) editor
;
90 this.userAdminWrapper
= userAdminWrapper
;
93 protected void createFormContent(final IManagedForm mf
) {
94 ScrolledForm form
= mf
.getForm();
95 Composite body
= form
.getBody();
96 GridLayout mainLayout
= new GridLayout();
97 body
.setLayout(mainLayout
);
98 Group group
= (Group
) editor
.getDisplayedUser();
99 appendOverviewPart(body
, group
);
100 appendMembersPart(body
, group
);
103 /** Creates the general section */
104 protected void appendOverviewPart(Composite parent
, final Group group
) {
105 FormToolkit tk
= getManagedForm().getToolkit();
106 Composite body
= addSection(tk
, parent
, "Main information");
107 GridLayout layout
= new GridLayout(2, false);
108 body
.setLayout(layout
);
110 final Text dnTxt
= createLT(body
, "DN",
111 UiAdminUtils
.getProperty(group
, LdifName
.dn
.name()));
112 dnTxt
.setEnabled(false);
114 final Text cnTxt
= createLT(body
, "Common Name",
115 UiAdminUtils
.getProperty(group
, LdifName
.cn
.name()));
116 cnTxt
.setEnabled(false);
118 Label descLbl
= new Label(body
, SWT
.LEAD
);
119 descLbl
.setText("Description");
120 descLbl
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.TOP
, false, false));
121 final Text descTxt
= new Text(body
, SWT
.LEAD
| SWT
.MULTI
| SWT
.WRAP
123 GridData gd
= EclipseUiUtils
.fillAll();
125 descTxt
.setLayoutData(gd
);
127 // create form part (controller)
128 AbstractFormPart part
= new SectionPart((Section
) body
.getParent()) {
130 private MainInfoListener listener
;
133 public void initialize(IManagedForm form
) {
134 super.initialize(form
);
135 listener
= editor
.new MainInfoListener(this);
136 userAdminWrapper
.addListener(listener
);
140 public void dispose() {
141 userAdminWrapper
.removeListener(listener
);
145 @SuppressWarnings("unchecked")
146 public void commit(boolean onSave
) {
147 group
.getProperties().put(LdifName
.description
.name(),
149 // Enable common name ?
150 // editor.setProperty(UserAdminConstants.KEY_CN,
152 super.commit(onSave
);
156 public void refresh() {
157 refreshFormTitle(group
);
158 dnTxt
.setText(group
.getName());
159 cnTxt
.setText(UiAdminUtils
.getProperty(group
,
160 LdifName
.cn
.name()));
161 descTxt
.setText(UiAdminUtils
.getProperty(group
,
162 LdifName
.description
.name()));
167 ModifyListener defaultListener
= editor
.new FormPartML(part
);
168 descTxt
.addModifyListener(defaultListener
);
169 getManagedForm().addPart(part
);
172 /** Filtered table with members. Has drag & drop ability */
173 protected void appendMembersPart(Composite parent
, Group group
) {
175 FormToolkit tk
= getManagedForm().getToolkit();
176 Section section
= tk
.createSection(parent
, Section
.TITLE_BAR
);
177 section
.setLayoutData(EclipseUiUtils
.fillAll());
179 // Composite body = tk.createComposite(section, SWT.NONE);
180 Composite body
= new Composite(section
, SWT
.NO_FOCUS
);
181 section
.setClient(body
);
182 body
.setLayoutData(EclipseUiUtils
.fillAll());
184 LdifUsersTable userTableViewerCmp
= createMemberPart(body
, group
);
186 // create form part (controller)
187 SectionPart part
= new GroupMembersPart(section
, userTableViewerCmp
,
189 getManagedForm().addPart(part
);
190 addRemoveAbitily(part
, userTableViewerCmp
.getTableViewer(), group
);
193 public LdifUsersTable
createMemberPart(Composite parent
, Group group
) {
194 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
195 // Define the displayed columns
196 List
<ColumnDefinition
> columnDefs
= new ArrayList
<ColumnDefinition
>();
197 columnDefs
.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
198 columnDefs
.add(new ColumnDefinition(new CommonNameLP(), "Common Name",
200 columnDefs
.add(new ColumnDefinition(new MailLP(), "Primary Mail", 150));
201 columnDefs
.add(new ColumnDefinition(new UserNameLP(),
202 "Distinguished Name", 240));
204 // Create and configure the table
205 LdifUsersTable userViewerCmp
= new MyUserTableViewer(parent
, SWT
.MULTI
206 | SWT
.H_SCROLL
| SWT
.V_SCROLL
, userAdminWrapper
.getUserAdmin());
208 userViewerCmp
.setColumnDefinitions(columnDefs
);
209 userViewerCmp
.populate(true, false);
210 userViewerCmp
.setLayoutData(EclipseUiUtils
.fillAll());
213 TableViewer userViewer
= userViewerCmp
.getTableViewer();
214 userViewer
.addDoubleClickListener(new UserTableDefaultDClickListener());
215 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
216 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
217 userViewer
.addDropSupport(operations
, tt
,
218 new GroupDropListener(userAdminWrapper
, userViewerCmp
,
219 (Group
) editor
.getDisplayedUser()));
221 return userViewerCmp
;
226 private class MyUserTableViewer
extends LdifUsersTable
{
227 private static final long serialVersionUID
= 8467999509931900367L;
229 private final UserFilter userFilter
;
231 public MyUserTableViewer(Composite parent
, int style
,
232 UserAdmin userAdmin
) {
233 super(parent
, style
, true);
234 userFilter
= new UserFilter();
239 protected List
<User
> listFilteredElements(String filter
) {
240 Group group
= (Group
) editor
.getDisplayedUser();
241 Role
[] roles
= group
.getMembers();
242 List
<User
> users
= new ArrayList
<User
>();
243 userFilter
.setSearchText(filter
);
244 for (Role role
: roles
)
245 // if (role.getType() == Role.GROUP)
246 if (userFilter
.select(null, null, role
))
247 users
.add((User
) role
);
252 private void addRemoveAbitily(SectionPart sectionPart
,
253 TableViewer userViewer
, Group group
) {
254 Section section
= sectionPart
.getSection();
255 ToolBarManager toolBarManager
= new ToolBarManager(SWT
.FLAT
);
256 ToolBar toolbar
= toolBarManager
.createControl(section
);
257 final Cursor handCursor
= new Cursor(section
.getDisplay(),
259 toolbar
.setCursor(handCursor
);
260 toolbar
.addDisposeListener(new DisposeListener() {
261 private static final long serialVersionUID
= 3882131405820522925L;
263 public void widgetDisposed(DisposeEvent e
) {
264 if ((handCursor
!= null) && (handCursor
.isDisposed() == false)) {
265 handCursor
.dispose();
270 Action action
= new RemoveMembershipAction(userViewer
, group
,
271 "Remove selected items from this group",
272 SecurityAdminImages
.ICON_REMOVE_DESC
);
273 toolBarManager
.add(action
);
274 toolBarManager
.update(true);
275 section
.setTextClient(toolbar
);
278 private class RemoveMembershipAction
extends Action
{
279 private static final long serialVersionUID
= -1337713097184522588L;
281 private final TableViewer userViewer
;
282 private final Group group
;
284 RemoveMembershipAction(TableViewer userViewer
, Group group
,
285 String name
, ImageDescriptor img
) {
287 this.userViewer
= userViewer
;
293 ISelection selection
= userViewer
.getSelection();
294 if (selection
.isEmpty())
297 @SuppressWarnings("unchecked")
298 Iterator
<User
> it
= ((IStructuredSelection
) selection
).iterator();
299 List
<User
> users
= new ArrayList
<User
>();
300 // StringBuilder builder = new StringBuilder();
301 while (it
.hasNext()) {
302 User currUser
= it
.next();
303 // String groupName = UiAdminUtils.getUsername(currGroup);
304 // builder.append(groupName).append("; ");
308 userAdminWrapper
.beginTransactionIfNeeded();
309 for (User user
: users
) {
310 group
.removeMember(user
);
312 userAdminWrapper
.notifyListeners(new UserAdminEvent(null,
313 UserAdminEvent
.ROLE_CHANGED
, group
));
318 private class GroupMembersPart
extends SectionPart
{
319 private final LdifUsersTable userViewer
;
320 private final Group group
;
322 private GroupChangeListener listener
;
324 public GroupMembersPart(Section section
, LdifUsersTable userViewer
,
327 this.userViewer
= userViewer
;
332 public void initialize(IManagedForm form
) {
333 super.initialize(form
);
334 listener
= editor
.new GroupChangeListener(GroupMembersPart
.this);
335 userAdminWrapper
.addListener(listener
);
339 public void dispose() {
340 userAdminWrapper
.removeListener(listener
);
345 public void refresh() {
346 refreshFormTitle(group
);
347 getSection().setText(
349 + UiAdminUtils
.getProperty(group
,
350 LdifName
.cn
.name()));
351 userViewer
.refresh();
357 * Defines this table as being a potential target to add group membership
358 * (roles) to this group
360 private class GroupDropListener
extends ViewerDropAdapter
{
361 private static final long serialVersionUID
= 2893468717831451621L;
363 private final UserAdminWrapper userAdminWrapper
;
364 // private final LdifUsersTable myUserViewerCmp;
365 private final Group myGroup
;
367 public GroupDropListener(UserAdminWrapper userAdminWrapper
,
368 LdifUsersTable userTableViewerCmp
, Group group
) {
369 super(userTableViewerCmp
.getTableViewer());
370 this.userAdminWrapper
= userAdminWrapper
;
371 this.myGroup
= group
;
372 // this.myUserViewerCmp = userTableViewerCmp;
376 public boolean validateDrop(Object target
, int operation
,
377 TransferData transferType
) {
378 // Target is always OK in a list only view
379 // TODO check if not a string
380 boolean validDrop
= true;
385 public void drop(DropTargetEvent event
) {
386 // TODO Is there an opportunity to perform ceck before?
388 String newUserName
= (String
) event
.data
;
389 UserAdmin myUserAdmin
= userAdminWrapper
.getUserAdmin();
390 Role role
= myUserAdmin
.getRole(newUserName
);
391 if (role
.getType() == Role
.GROUP
) {
392 Group newGroup
= (Group
) role
;
393 Shell shell
= getViewer().getControl().getShell();
395 if (myGroup
== newGroup
) { // Equality
396 MessageDialog
.openError(shell
, "Forbidden addition ",
397 "A group cannot be a member of itself.");
402 String myName
= myGroup
.getName();
403 List
<User
> myMemberships
= editor
.getFlatGroups(myGroup
);
404 if (myMemberships
.contains(newGroup
)) {
405 MessageDialog
.openError(shell
, "Forbidden addition: cycle",
406 "Cannot add " + newUserName
+ " to group " + myName
407 + ". This would create a cycle");
412 List
<User
> newGroupMemberships
= editor
.getFlatGroups(newGroup
);
413 if (newGroupMemberships
.contains(myGroup
)) {
414 MessageDialog
.openError(shell
, "Forbidden addition",
415 "Cannot add " + newUserName
+ " to group " + myName
416 + ", this membership already exists");
419 userAdminWrapper
.beginTransactionIfNeeded();
420 // TODO implement the dirty state
421 myGroup
.addMember(newGroup
);
422 userAdminWrapper
.notifyListeners(new UserAdminEvent(null,
423 UserAdminEvent
.ROLE_CHANGED
, myGroup
));
424 } else if (role
.getType() == Role
.USER
) {
425 // TODO check if the group is already member of this group
426 userAdminWrapper
.beginTransactionIfNeeded();
427 User user
= (User
) role
;
428 myGroup
.addMember(user
);
429 userAdminWrapper
.notifyListeners(new UserAdminEvent(null,
430 UserAdminEvent
.ROLE_CHANGED
, myGroup
));
436 public boolean performDrop(Object data
) {
437 // myUserViewerCmp.refresh();
443 private void refreshFormTitle(Group group
) {
444 getManagedForm().getForm().setText(
445 UiAdminUtils
.getProperty(group
, LdifName
.cn
.name()));
448 private Composite
addSection(FormToolkit tk
, Composite parent
, String title
) {
449 Section section
= tk
.createSection(parent
, Section
.TITLE_BAR
);
450 GridData gd
= EclipseUiUtils
.fillWidth();
451 gd
.verticalAlignment
= PRE_TITLE_INDENT
;
452 section
.setLayoutData(gd
);
453 section
.setText(title
);
454 Composite body
= tk
.createComposite(section
, SWT
.WRAP
);
455 body
.setLayoutData(EclipseUiUtils
.fillAll());
456 section
.setClient(body
);
460 /** Creates label and text. */
461 private Text
createLT(Composite body
, String label
, String value
) {
462 FormToolkit toolkit
= getManagedForm().getToolkit();
463 Label lbl
= toolkit
.createLabel(body
, label
);
464 lbl
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.CENTER
, false, false));
465 Text text
= toolkit
.createText(body
, value
, SWT
.BORDER
);
466 text
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));