]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java
f3fdabfb19ccf16650e664280ef4963686aca5b7
[lgpl/argeo-commons.git] / org.argeo.security.ui.admin / src / org / argeo / security / ui / admin / internal / parts / GroupMainPage.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 package org.argeo.security.ui.admin.internal.parts;
17
18 import java.util.ArrayList;
19 import java.util.Iterator;
20 import java.util.List;
21
22 import org.argeo.eclipse.ui.EclipseUiUtils;
23 import org.argeo.jcr.ArgeoNames;
24 import org.argeo.security.ui.admin.SecurityAdminImages;
25 import org.argeo.security.ui.admin.internal.ColumnDefinition;
26 import org.argeo.security.ui.admin.internal.UiAdminUtils;
27 import org.argeo.security.ui.admin.internal.UserAdminConstants;
28 import org.argeo.security.ui.admin.internal.UserAdminWrapper;
29 import org.argeo.security.ui.admin.internal.UserTableViewer;
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.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.dialogs.MessageDialog;
40 import org.eclipse.jface.resource.ImageDescriptor;
41 import org.eclipse.jface.viewers.ISelection;
42 import org.eclipse.jface.viewers.IStructuredSelection;
43 import org.eclipse.jface.viewers.TableViewer;
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.graphics.Cursor;
54 import org.eclipse.swt.layout.GridData;
55 import org.eclipse.swt.layout.GridLayout;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Label;
58 import org.eclipse.swt.widgets.Shell;
59 import org.eclipse.swt.widgets.Text;
60 import org.eclipse.swt.widgets.ToolBar;
61 import org.eclipse.ui.forms.AbstractFormPart;
62 import org.eclipse.ui.forms.IManagedForm;
63 import org.eclipse.ui.forms.SectionPart;
64 import org.eclipse.ui.forms.editor.FormEditor;
65 import org.eclipse.ui.forms.editor.FormPage;
66 import org.eclipse.ui.forms.widgets.FormToolkit;
67 import org.eclipse.ui.forms.widgets.ScrolledForm;
68 import org.eclipse.ui.forms.widgets.Section;
69 import org.osgi.service.useradmin.Group;
70 import org.osgi.service.useradmin.Role;
71 import org.osgi.service.useradmin.User;
72 import org.osgi.service.useradmin.UserAdmin;
73 import org.osgi.service.useradmin.UserAdminEvent;
74
75 /** Display/edit main properties of a given group */
76 public class GroupMainPage extends FormPage implements ArgeoNames {
77 final static String ID = "GroupEditor.mainPage";
78
79 private final UserEditor editor;
80 private UserAdminWrapper userAdminWrapper;
81
82 // Local configuration
83 private final int PRE_TITLE_INDENT = 10;
84
85 public GroupMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper) {
86 super(editor, ID, "Main");
87 this.editor = (UserEditor) editor;
88 this.userAdminWrapper = userAdminWrapper;
89 }
90
91 protected void createFormContent(final IManagedForm mf) {
92 ScrolledForm form = mf.getForm();
93 Composite body = form.getBody();
94 GridLayout mainLayout = new GridLayout();
95 body.setLayout(mainLayout);
96 Group group = (Group) editor.getDisplayedUser();
97 appendOverviewPart(body, group);
98 appendMembersPart(body, group);
99 }
100
101 /** Creates the general section */
102 protected void appendOverviewPart(Composite parent, final Group group) {
103 FormToolkit tk = getManagedForm().getToolkit();
104 Composite body = addSection(tk, parent, "Main information");
105 GridLayout layout = new GridLayout(2, false);
106 body.setLayout(layout);
107
108 final Text distinguishedName = createLT(body, "Group Name",
109 UiAdminUtils.getProperty(group, UserAdminConstants.KEY_UID));
110 distinguishedName.setEnabled(false);
111
112 final Text commonName = createLT(body, "Common Name",
113 UiAdminUtils.getProperty(group, UserAdminConstants.KEY_CN));
114 commonName.setEnabled(false);
115
116 // create form part (controller)
117 AbstractFormPart part = new SectionPart((Section) body.getParent()) {
118
119 private MainInfoListener listener;
120
121 @Override
122 public void initialize(IManagedForm form) {
123 super.initialize(form);
124 listener = editor.new MainInfoListener(this);
125 userAdminWrapper.addListener(listener);
126 }
127
128 @Override
129 public void dispose() {
130 userAdminWrapper.removeListener(listener);
131 super.dispose();
132 }
133
134 @Override
135 public void refresh() {
136 refreshFormTitle(group);
137 distinguishedName.setText(UiAdminUtils.getProperty(group,
138 UserAdminConstants.KEY_UID));
139 commonName.setText(UiAdminUtils.getProperty(group,
140 UserAdminConstants.KEY_CN));
141 super.refresh();
142 }
143 };
144 getManagedForm().addPart(part);
145 }
146
147 /** Filtered table with members. Has drag & drop ability */
148 protected void appendMembersPart(Composite parent, Group group) {
149
150 FormToolkit tk = getManagedForm().getToolkit();
151 Section section = tk.createSection(parent, Section.TITLE_BAR);
152 section.setLayoutData(EclipseUiUtils.fillAll());
153
154 // Composite body = tk.createComposite(section, SWT.NONE);
155 Composite body = new Composite(section, SWT.NO_FOCUS);
156 section.setClient(body);
157 body.setLayoutData(EclipseUiUtils.fillAll());
158
159 UserTableViewer userTableViewerCmp = createMemberPart(body, group);
160
161 // create form part (controller)
162 SectionPart part = new GroupMembersPart(section, userTableViewerCmp,
163 group);
164 getManagedForm().addPart(part);
165 addRemoveAbitily(part, userTableViewerCmp.getTableViewer(), group);
166 }
167
168 public UserTableViewer createMemberPart(Composite parent, Group group) {
169 parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
170 // Define the displayed columns
171 List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
172 columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
173 columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Common Name",
174 150));
175 columnDefs.add(new ColumnDefinition(new MailLP(), "Primary Mail", 150));
176 columnDefs.add(new ColumnDefinition(new UserNameLP(),
177 "Distinguished Name", 240));
178
179 // Create and configure the table
180 UserTableViewer userViewerCmp = new MyUserTableViewer(parent, SWT.MULTI
181 | SWT.H_SCROLL | SWT.V_SCROLL, userAdminWrapper.getUserAdmin());
182
183 userViewerCmp.setColumnDefinitions(columnDefs);
184 userViewerCmp.populate(true, false);
185 userViewerCmp.setLayoutData(EclipseUiUtils.fillAll());
186
187 // Controllers
188 TableViewer userViewer = userViewerCmp.getTableViewer();
189 userViewer.addDoubleClickListener(new UserTableDefaultDClickListener());
190 int operations = DND.DROP_COPY | DND.DROP_MOVE;
191 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
192 userViewer.addDropSupport(operations, tt,
193 new GroupDropListener(userAdminWrapper, userViewerCmp,
194 (Group) editor.getDisplayedUser()));
195
196 return userViewerCmp;
197 }
198
199 // Local viewers
200
201 private class MyUserTableViewer extends UserTableViewer {
202 private static final long serialVersionUID = 8467999509931900367L;
203
204 public MyUserTableViewer(Composite parent, int style,
205 UserAdmin userAdmin) {
206 super(parent, style, userAdmin, true);
207 }
208
209 @Override
210 protected List<User> listFilteredElements(String filter) {
211 Group group = (Group) editor.getDisplayedUser();
212 Role[] roles = group.getMembers();
213 List<User> users = new ArrayList<User>();
214 for (Role role : roles)
215 // if (role.getType() == Role.GROUP)
216 users.add((User) role);
217 return users;
218 }
219 }
220
221 private void addRemoveAbitily(SectionPart sectionPart,
222 TableViewer userViewer, Group group) {
223 Section section = sectionPart.getSection();
224 ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
225 ToolBar toolbar = toolBarManager.createControl(section);
226 final Cursor handCursor = new Cursor(section.getDisplay(),
227 SWT.CURSOR_HAND);
228 toolbar.setCursor(handCursor);
229 toolbar.addDisposeListener(new DisposeListener() {
230 private static final long serialVersionUID = 3882131405820522925L;
231
232 public void widgetDisposed(DisposeEvent e) {
233 if ((handCursor != null) && (handCursor.isDisposed() == false)) {
234 handCursor.dispose();
235 }
236 }
237 });
238
239 Action action = new RemoveMembershipAction(userViewer, group,
240 "Remove selected items from this group",
241 SecurityAdminImages.ICON_REMOVE_DESC);
242 toolBarManager.add(action);
243 toolBarManager.update(true);
244 section.setTextClient(toolbar);
245 }
246
247 private class RemoveMembershipAction extends Action {
248 private static final long serialVersionUID = -1337713097184522588L;
249
250 private final TableViewer userViewer;
251 private final Group group;
252
253 RemoveMembershipAction(TableViewer userViewer, Group group,
254 String name, ImageDescriptor img) {
255 super(name, img);
256 this.userViewer = userViewer;
257 this.group = group;
258 }
259
260 @Override
261 public void run() {
262 ISelection selection = userViewer.getSelection();
263 if (selection.isEmpty())
264 return;
265
266 @SuppressWarnings("unchecked")
267 Iterator<User> it = ((IStructuredSelection) selection).iterator();
268 List<User> users = new ArrayList<User>();
269 // StringBuilder builder = new StringBuilder();
270 while (it.hasNext()) {
271 User currUser = it.next();
272 // String groupName = UiAdminUtils.getUsername(currGroup);
273 // builder.append(groupName).append("; ");
274 users.add(currUser);
275 }
276
277 userAdminWrapper.beginTransactionIfNeeded();
278 for (User user : users) {
279 group.removeMember(user);
280 }
281 userAdminWrapper.notifyListeners(new UserAdminEvent(null,
282 UserAdminEvent.ROLE_CHANGED, group));
283 }
284 }
285
286 // LOCAL CONTROLLERS
287 private class GroupMembersPart extends SectionPart {
288 private final UserTableViewer userViewer;
289 private final Group group;
290
291 private GroupChangeListener listener;
292
293 public GroupMembersPart(Section section, UserTableViewer userViewer,
294 Group group) {
295 super(section);
296 this.userViewer = userViewer;
297 this.group = group;
298 }
299
300 @Override
301 public void initialize(IManagedForm form) {
302 super.initialize(form);
303 listener = editor.new GroupChangeListener(GroupMembersPart.this);
304 userAdminWrapper.addListener(listener);
305 }
306
307 @Override
308 public void dispose() {
309 userAdminWrapper.removeListener(listener);
310 super.dispose();
311 }
312
313 @Override
314 public void refresh() {
315 refreshFormTitle(group);
316 getSection().setText(
317 "Members of group "
318 + UiAdminUtils.getProperty(group,
319 UserAdminConstants.KEY_CN));
320 userViewer.refresh();
321 super.refresh();
322 }
323 }
324
325 /**
326 * Defines this table as being a potential target to add group membership
327 * (roles) to this group
328 */
329 private class GroupDropListener extends ViewerDropAdapter {
330 private static final long serialVersionUID = 2893468717831451621L;
331
332 private final UserAdminWrapper userAdminWrapper;
333 // private final UserTableViewer myUserViewerCmp;
334 private final Group myGroup;
335
336 public GroupDropListener(UserAdminWrapper userAdminWrapper,
337 UserTableViewer userTableViewerCmp, Group group) {
338 super(userTableViewerCmp.getTableViewer());
339 this.userAdminWrapper = userAdminWrapper;
340 this.myGroup = group;
341 // this.myUserViewerCmp = userTableViewerCmp;
342 }
343
344 @Override
345 public boolean validateDrop(Object target, int operation,
346 TransferData transferType) {
347 // Target is always OK in a list only view
348 // TODO check if not a string
349 boolean validDrop = true;
350 return validDrop;
351 }
352
353 @Override
354 public void drop(DropTargetEvent event) {
355 // TODO Is there an opportunity to perform ceck before?
356
357 String newUserName = (String) event.data;
358 UserAdmin myUserAdmin = userAdminWrapper.getUserAdmin();
359 Role role = myUserAdmin.getRole(newUserName);
360 if (role.getType() == Role.USER) {
361 // TODO check if the group is already member of this group
362 userAdminWrapper.beginTransactionIfNeeded();
363 User user = (User) role;
364 myGroup.addMember(user);
365 userAdminWrapper.notifyListeners(new UserAdminEvent(null,
366 UserAdminEvent.ROLE_CHANGED, myGroup));
367 } else if (role.getType() == Role.GROUP) {
368 Group newGroup = (Group) role;
369
370 Shell shell = getViewer().getControl().getShell();
371 // Sanity checks
372 if (myGroup == newGroup) { // Equality
373 MessageDialog.openError(shell, "Forbidden addition ",
374 "A group cannot be a member of itself.");
375 return;
376 }
377
378 // Cycle
379 String myName = myGroup.getName();
380 List<User> myMemberships = editor.getFlatGroups(myGroup);
381 if (myMemberships.contains(newGroup)) {
382 MessageDialog.openError(shell, "Forbidden addition: cycle",
383 "Cannot add " + newUserName + " to group " + myName
384 + ". This would create a cycle");
385 return;
386 }
387
388 // Already member
389 List<User> newGroupMemberships = editor.getFlatGroups(newGroup);
390 if (newGroupMemberships.contains(myGroup)) {
391 MessageDialog.openError(shell, "Forbidden addition",
392 "Cannot add " + newUserName + " to group " + myName
393 + ", this membership already exists");
394 return;
395 }
396
397 userAdminWrapper.beginTransactionIfNeeded();
398 // TODO implement the dirty state
399 myGroup.addMember(newGroup);
400 userAdminWrapper.notifyListeners(new UserAdminEvent(null,
401 UserAdminEvent.ROLE_CHANGED, myGroup));
402 }
403 super.drop(event);
404 }
405
406 @Override
407 public boolean performDrop(Object data) {
408 // myUserViewerCmp.refresh();
409 return true;
410 }
411 }
412
413 // LOCAL HELPERS
414 private void refreshFormTitle(Group group) {
415 getManagedForm().getForm().setText(
416 UiAdminUtils.getProperty(group, UserAdminConstants.KEY_CN));
417 }
418
419 private Composite addSection(FormToolkit tk, Composite parent, String title) {
420 Section section = tk.createSection(parent, Section.TITLE_BAR);
421 GridData gd = EclipseUiUtils.fillWidth();
422 gd.verticalAlignment = PRE_TITLE_INDENT;
423 section.setLayoutData(gd);
424 section.setText(title);
425 Composite body = tk.createComposite(section, SWT.WRAP);
426 body.setLayoutData(EclipseUiUtils.fillAll());
427 section.setClient(body);
428 return body;
429 }
430
431 /** Creates label and text. */
432 private Text createLT(Composite body, String label, String value) {
433 FormToolkit toolkit = getManagedForm().getToolkit();
434 Label lbl = toolkit.createLabel(body, label);
435 lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
436 Text text = toolkit.createText(body, value, SWT.BORDER);
437 text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
438 return text;
439 }
440 }