]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java
Fix URI when using default LDIF
[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.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;
76
77 /** Display/edit main properties of a given group */
78 public class GroupMainPage extends FormPage implements ArgeoNames {
79 final static String ID = "GroupEditor.mainPage";
80
81 private final UserEditor editor;
82 private UserAdminWrapper userAdminWrapper;
83
84 // Local configuration
85 private final int PRE_TITLE_INDENT = 10;
86
87 public GroupMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper) {
88 super(editor, ID, "Main");
89 this.editor = (UserEditor) editor;
90 this.userAdminWrapper = userAdminWrapper;
91 }
92
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);
101 }
102
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);
109
110 final Text dnTxt = createLT(body, "DN",
111 UiAdminUtils.getProperty(group, LdifName.dn.name()));
112 dnTxt.setEnabled(false);
113
114 final Text cnTxt = createLT(body, "Common Name",
115 UiAdminUtils.getProperty(group, LdifName.cn.name()));
116 cnTxt.setEnabled(false);
117
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
122 | SWT.BORDER);
123 GridData gd = EclipseUiUtils.fillAll();
124 gd.heightHint = 100;
125 descTxt.setLayoutData(gd);
126
127 // create form part (controller)
128 AbstractFormPart part = new SectionPart((Section) body.getParent()) {
129
130 private MainInfoListener listener;
131
132 @Override
133 public void initialize(IManagedForm form) {
134 super.initialize(form);
135 listener = editor.new MainInfoListener(this);
136 userAdminWrapper.addListener(listener);
137 }
138
139 @Override
140 public void dispose() {
141 userAdminWrapper.removeListener(listener);
142 super.dispose();
143 }
144
145 @SuppressWarnings("unchecked")
146 public void commit(boolean onSave) {
147 group.getProperties().put(LdifName.description.name(),
148 descTxt.getText());
149 // Enable common name ?
150 // editor.setProperty(UserAdminConstants.KEY_CN,
151 // email.getText());
152 super.commit(onSave);
153 }
154
155 @Override
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()));
163 super.refresh();
164 }
165 };
166
167 ModifyListener defaultListener = editor.new FormPartML(part);
168 descTxt.addModifyListener(defaultListener);
169 getManagedForm().addPart(part);
170 }
171
172 /** Filtered table with members. Has drag & drop ability */
173 protected void appendMembersPart(Composite parent, Group group) {
174
175 FormToolkit tk = getManagedForm().getToolkit();
176 Section section = tk.createSection(parent, Section.TITLE_BAR);
177 section.setLayoutData(EclipseUiUtils.fillAll());
178
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());
183
184 LdifUsersTable userTableViewerCmp = createMemberPart(body, group);
185
186 // create form part (controller)
187 SectionPart part = new GroupMembersPart(section, userTableViewerCmp,
188 group);
189 getManagedForm().addPart(part);
190 addRemoveAbitily(part, userTableViewerCmp.getTableViewer(), group);
191 }
192
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",
199 150));
200 columnDefs.add(new ColumnDefinition(new MailLP(), "Primary Mail", 150));
201 columnDefs.add(new ColumnDefinition(new UserNameLP(),
202 "Distinguished Name", 240));
203
204 // Create and configure the table
205 LdifUsersTable userViewerCmp = new MyUserTableViewer(parent, SWT.MULTI
206 | SWT.H_SCROLL | SWT.V_SCROLL, userAdminWrapper.getUserAdmin());
207
208 userViewerCmp.setColumnDefinitions(columnDefs);
209 userViewerCmp.populate(true, false);
210 userViewerCmp.setLayoutData(EclipseUiUtils.fillAll());
211
212 // Controllers
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()));
220
221 return userViewerCmp;
222 }
223
224 // Local viewers
225
226 private class MyUserTableViewer extends LdifUsersTable {
227 private static final long serialVersionUID = 8467999509931900367L;
228
229 private final UserFilter userFilter;
230
231 public MyUserTableViewer(Composite parent, int style,
232 UserAdmin userAdmin) {
233 super(parent, style, true);
234 userFilter = new UserFilter();
235
236 }
237
238 @Override
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);
248 return users;
249 }
250 }
251
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(),
258 SWT.CURSOR_HAND);
259 toolbar.setCursor(handCursor);
260 toolbar.addDisposeListener(new DisposeListener() {
261 private static final long serialVersionUID = 3882131405820522925L;
262
263 public void widgetDisposed(DisposeEvent e) {
264 if ((handCursor != null) && (handCursor.isDisposed() == false)) {
265 handCursor.dispose();
266 }
267 }
268 });
269
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);
276 }
277
278 private class RemoveMembershipAction extends Action {
279 private static final long serialVersionUID = -1337713097184522588L;
280
281 private final TableViewer userViewer;
282 private final Group group;
283
284 RemoveMembershipAction(TableViewer userViewer, Group group,
285 String name, ImageDescriptor img) {
286 super(name, img);
287 this.userViewer = userViewer;
288 this.group = group;
289 }
290
291 @Override
292 public void run() {
293 ISelection selection = userViewer.getSelection();
294 if (selection.isEmpty())
295 return;
296
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("; ");
305 users.add(currUser);
306 }
307
308 userAdminWrapper.beginTransactionIfNeeded();
309 for (User user : users) {
310 group.removeMember(user);
311 }
312 userAdminWrapper.notifyListeners(new UserAdminEvent(null,
313 UserAdminEvent.ROLE_CHANGED, group));
314 }
315 }
316
317 // LOCAL CONTROLLERS
318 private class GroupMembersPart extends SectionPart {
319 private final LdifUsersTable userViewer;
320 private final Group group;
321
322 private GroupChangeListener listener;
323
324 public GroupMembersPart(Section section, LdifUsersTable userViewer,
325 Group group) {
326 super(section);
327 this.userViewer = userViewer;
328 this.group = group;
329 }
330
331 @Override
332 public void initialize(IManagedForm form) {
333 super.initialize(form);
334 listener = editor.new GroupChangeListener(GroupMembersPart.this);
335 userAdminWrapper.addListener(listener);
336 }
337
338 @Override
339 public void dispose() {
340 userAdminWrapper.removeListener(listener);
341 super.dispose();
342 }
343
344 @Override
345 public void refresh() {
346 refreshFormTitle(group);
347 getSection().setText(
348 "Members of group "
349 + UiAdminUtils.getProperty(group,
350 LdifName.cn.name()));
351 userViewer.refresh();
352 super.refresh();
353 }
354 }
355
356 /**
357 * Defines this table as being a potential target to add group membership
358 * (roles) to this group
359 */
360 private class GroupDropListener extends ViewerDropAdapter {
361 private static final long serialVersionUID = 2893468717831451621L;
362
363 private final UserAdminWrapper userAdminWrapper;
364 // private final LdifUsersTable myUserViewerCmp;
365 private final Group myGroup;
366
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;
373 }
374
375 @Override
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;
381 return validDrop;
382 }
383
384 @Override
385 public void drop(DropTargetEvent event) {
386 // TODO Is there an opportunity to perform ceck before?
387
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();
394 // Sanity checks
395 if (myGroup == newGroup) { // Equality
396 MessageDialog.openError(shell, "Forbidden addition ",
397 "A group cannot be a member of itself.");
398 return;
399 }
400
401 // Cycle
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");
408 return;
409 }
410
411 // Already member
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");
417 return;
418 }
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));
431 }
432 super.drop(event);
433 }
434
435 @Override
436 public boolean performDrop(Object data) {
437 // myUserViewerCmp.refresh();
438 return true;
439 }
440 }
441
442 // LOCAL HELPERS
443 private void refreshFormTitle(Group group) {
444 getManagedForm().getForm().setText(
445 UiAdminUtils.getProperty(group, LdifName.cn.name()));
446 }
447
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);
457 return body;
458 }
459
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));
467 return text;
468 }
469 }