]> git.argeo.org Git - lgpl/argeo-commons.git/blob - GroupEditor.java
a011c5f62c19c45fcdeca8ce4644ed732fe539f6
[lgpl/argeo-commons.git] / GroupEditor.java
1 package org.argeo.cms.e4.users;
2
3 import static org.argeo.api.cms.CmsContext.WORKGROUP;
4 import static org.argeo.cms.auth.UserAdminUtils.setProperty;
5 import static org.argeo.util.naming.LdapAttrs.businessCategory;
6 import static org.argeo.util.naming.LdapAttrs.description;
7
8 import java.util.ArrayList;
9 import java.util.Iterator;
10 import java.util.List;
11
12 import javax.annotation.PreDestroy;
13 import javax.inject.Inject;
14 import javax.jcr.Node;
15 import javax.jcr.Repository;
16 import javax.jcr.RepositoryException;
17 import javax.jcr.Session;
18
19 import org.argeo.api.cms.CmsConstants;
20 import org.argeo.api.cms.CmsContext;
21 import org.argeo.cms.auth.UserAdminUtils;
22 import org.argeo.cms.e4.users.providers.CommonNameLP;
23 import org.argeo.cms.e4.users.providers.MailLP;
24 import org.argeo.cms.e4.users.providers.RoleIconLP;
25 import org.argeo.cms.e4.users.providers.UserFilter;
26 import org.argeo.cms.jcr.CmsJcrUtils;
27 import org.argeo.cms.swt.CmsSwtUtils;
28 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
29 import org.argeo.cms.ui.eclipse.forms.IManagedForm;
30 import org.argeo.eclipse.ui.ColumnDefinition;
31 import org.argeo.eclipse.ui.EclipseUiUtils;
32 import org.argeo.eclipse.ui.parts.LdifUsersTable;
33 import org.argeo.jcr.JcrException;
34 import org.argeo.jcr.JcrUtils;
35 import org.argeo.osgi.transaction.WorkTransaction;
36 import org.argeo.util.naming.LdapAttrs;
37 import org.eclipse.e4.ui.workbench.modeling.EPartService;
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.ModifyListener;
53 import org.eclipse.swt.events.SelectionAdapter;
54 import org.eclipse.swt.events.SelectionEvent;
55 import org.eclipse.swt.layout.GridData;
56 import org.eclipse.swt.layout.GridLayout;
57 import org.eclipse.swt.widgets.Composite;
58 import org.eclipse.swt.widgets.Label;
59 import org.eclipse.swt.widgets.Link;
60 import org.eclipse.swt.widgets.Shell;
61 import org.eclipse.swt.widgets.Text;
62 import org.eclipse.swt.widgets.ToolBar;
63 import org.osgi.service.useradmin.Group;
64 import org.osgi.service.useradmin.Role;
65 //import org.eclipse.ui.forms.AbstractFormPart;
66 //import org.eclipse.ui.forms.IManagedForm;
67 //import org.eclipse.ui.forms.SectionPart;
68 //import org.eclipse.ui.forms.editor.FormEditor;
69 //import org.eclipse.ui.forms.editor.FormPage;
70 //import org.eclipse.ui.forms.widgets.FormToolkit;
71 //import org.eclipse.ui.forms.widgets.ScrolledForm;
72 //import org.eclipse.ui.forms.widgets.Section;
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 GroupEditor extends AbstractRoleEditor {
79 // final static String ID = "GroupEditor.mainPage";
80
81 @Inject
82 private EPartService partService;
83
84 // private final UserEditor editor;
85 @Inject
86 private Repository repository;
87 @Inject
88 private CmsContext nodeInstance;
89 // private final UserAdminWrapper userAdminWrapper;
90 private Session groupsSession;
91
92 // public GroupMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper,
93 // Repository repository,
94 // NodeInstance nodeInstance) {
95 // super(editor, ID, "Main");
96 // try {
97 // session = repository.login();
98 // } catch (RepositoryException e) {
99 // throw new CmsException("Cannot retrieve session of in MainGroupPage
100 // constructor", e);
101 // }
102 // this.editor = (UserEditor) editor;
103 // this.userAdminWrapper = userAdminWrapper;
104 // this.nodeInstance = nodeInstance;
105 // }
106
107 // protected void createFormContent(final IManagedForm mf) {
108 // ScrolledForm form = mf.getForm();
109 // Composite body = form.getBody();
110 // GridLayout mainLayout = new GridLayout();
111 // body.setLayout(mainLayout);
112 // Group group = (Group) editor.getDisplayedUser();
113 // appendOverviewPart(body, group);
114 // appendMembersPart(body, group);
115 // }
116
117 @Override
118 protected void createUi(Composite parent) {
119 try {
120 groupsSession = repository.login(CmsConstants.SRV_WORKSPACE);
121 } catch (RepositoryException e) {
122 throw new JcrException("Cannot retrieve session", e);
123 }
124 // ScrolledForm form = mf.getForm();
125 // Composite body = form.getBody();
126 // Composite body = new Composite(parent, SWT.NONE);
127 Composite body = parent;
128 GridLayout mainLayout = new GridLayout();
129 body.setLayout(mainLayout);
130 Group group = (Group) getDisplayedUser();
131 appendOverviewPart(body, group);
132 appendMembersPart(body, group);
133 }
134
135 @PreDestroy
136 public void dispose() {
137 JcrUtils.logoutQuietly(groupsSession);
138 super.dispose();
139 }
140
141 /** Creates the general section */
142 protected void appendOverviewPart(final Composite parent, final Group group) {
143 Composite body = new Composite(parent, SWT.NONE);
144 // GridLayout layout = new GridLayout(5, false);
145 GridLayout layout = new GridLayout(2, false);
146 body.setLayout(layout);
147 body.setLayoutData(CmsSwtUtils.fillWidth());
148
149 String cn = UserAdminUtils.getProperty(group, LdapAttrs.cn.name());
150 createReadOnlyLT(body, "Name", cn);
151 createReadOnlyLT(body, "DN", group.getName());
152 createReadOnlyLT(body, "Domain", UserAdminUtils.getDomainName(group));
153
154 // Description
155 Label descLbl = new Label(body, SWT.LEAD);
156 descLbl.setFont(EclipseUiUtils.getBoldFont(body));
157 descLbl.setText("Description");
158 descLbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, false, 2, 1));
159 final Text descTxt = new Text(body, SWT.LEAD | SWT.MULTI | SWT.WRAP | SWT.BORDER);
160 GridData gd = EclipseUiUtils.fillWidth();
161 gd.heightHint = 50;
162 gd.horizontalSpan = 2;
163 descTxt.setLayoutData(gd);
164
165 // Mark as workgroup
166 Link markAsWorkgroupLk = new Link(body, SWT.NONE);
167 markAsWorkgroupLk.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
168
169 // create form part (controller)
170 final AbstractFormPart part = new AbstractFormPart() {
171
172 private MainInfoListener listener;
173
174 @Override
175 public void initialize(IManagedForm form) {
176 super.initialize(form);
177 listener = new MainInfoListener(parent.getDisplay(), this);
178 userAdminWrapper.addListener(listener);
179 }
180
181 @Override
182 public void dispose() {
183 userAdminWrapper.removeListener(listener);
184 super.dispose();
185 }
186
187 public void commit(boolean onSave) {
188 // group.getProperties().put(LdapAttrs.description.name(), descTxt.getText());
189 setProperty(group, description, descTxt.getText());
190 super.commit(onSave);
191 }
192
193 @Override
194 public void refresh() {
195 // dnTxt.setText(group.getName());
196 // cnTxt.setText(UserAdminUtils.getProperty(group, LdapAttrs.cn.name()));
197 descTxt.setText(UserAdminUtils.getProperty(group, LdapAttrs.description.name()));
198 Node workgroupHome = CmsJcrUtils.getGroupHome(groupsSession, cn);
199 if (workgroupHome == null)
200 markAsWorkgroupLk.setText("<a>Mark as workgroup</a>");
201 else
202 markAsWorkgroupLk.setText("Configured as workgroup");
203 parent.layout(true, true);
204 super.refresh();
205 }
206 };
207
208 markAsWorkgroupLk.addSelectionListener(new SelectionAdapter() {
209 private static final long serialVersionUID = -6439340898096365078L;
210
211 @Override
212 public void widgetSelected(SelectionEvent e) {
213
214 boolean confirmed = MessageDialog.openConfirm(parent.getShell(), "Mark as workgroup",
215 "Are you sure you want to mark " + cn + " as being a workgroup? ");
216 if (confirmed) {
217 Node workgroupHome = CmsJcrUtils.getGroupHome(groupsSession, cn);
218 if (workgroupHome != null)
219 return; // already marked as workgroup, do nothing
220 else {
221 // improve transaction management
222 userAdminWrapper.beginTransactionIfNeeded();
223 nodeInstance.createWorkgroup(group.getName());
224 setProperty(group, businessCategory, WORKGROUP);
225 userAdminWrapper.commitOrNotifyTransactionStateChange();
226 userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group));
227 part.refresh();
228 }
229 }
230 }
231 });
232
233 ModifyListener defaultListener = new FormPartML(part);
234 descTxt.addModifyListener(defaultListener);
235 getManagedForm().addPart(part);
236 }
237
238 /** Filtered table with members. Has drag and drop ability */
239 protected void appendMembersPart(Composite parent, Group group) {
240 // Section section = tk.createSection(parent, Section.TITLE_BAR);
241 // section.setText("Members");
242 // section.setLayoutData(EclipseUiUtils.fillAll());
243
244 Composite body = new Composite(parent, SWT.BORDER);
245 body.setLayout(new GridLayout());
246 // section.setClient(body);
247 body.setLayoutData(EclipseUiUtils.fillAll());
248
249 // Define the displayed columns
250 List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
251 columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
252 columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150));
253 columnDefs.add(new ColumnDefinition(new MailLP(), "Mail", 150));
254 // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name",
255 // 240));
256
257 // Create and configure the table
258 LdifUsersTable userViewerCmp = new MyUserTableViewer(body, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL,
259 userAdminWrapper.getUserAdmin());
260
261 userViewerCmp.setColumnDefinitions(columnDefs);
262 userViewerCmp.populate(true, false);
263 userViewerCmp.setLayoutData(EclipseUiUtils.fillAll());
264
265 // Controllers
266 TableViewer userViewer = userViewerCmp.getTableViewer();
267 userViewer.addDoubleClickListener(new UserTableDefaultDClickListener(partService));
268 int operations = DND.DROP_COPY | DND.DROP_MOVE;
269 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
270 userViewer.addDropSupport(operations, tt,
271 new GroupDropListener(userAdminWrapper, userViewerCmp, (Group) getDisplayedUser()));
272
273 AbstractFormPart part = new GroupMembersPart(userViewerCmp);
274 getManagedForm().addPart(part);
275
276 // remove button
277 // addRemoveAbility(toolBarManager, userViewerCmp.getTableViewer(), group);
278 Action action = new RemoveMembershipAction(userViewer, group, "Remove selected items from this group",
279 SecurityAdminImages.ICON_REMOVE_DESC);
280
281 ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
282 ToolBar toolBar = toolBarManager.createControl(body);
283 toolBar.setLayoutData(CmsSwtUtils.fillWidth());
284
285 toolBarManager.add(action);
286 toolBarManager.update(true);
287
288 }
289
290 // private LdifUsersTable createMemberPart(Composite parent, Group group) {
291 //
292 // // Define the displayed columns
293 // List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
294 // columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24));
295 // columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150));
296 // columnDefs.add(new ColumnDefinition(new MailLP(), "Mail", 150));
297 // // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished
298 // Name",
299 // // 240));
300 //
301 // // Create and configure the table
302 // LdifUsersTable userViewerCmp = new MyUserTableViewer(parent, SWT.MULTI |
303 // SWT.H_SCROLL | SWT.V_SCROLL,
304 // userAdminWrapper.getUserAdmin());
305 //
306 // userViewerCmp.setColumnDefinitions(columnDefs);
307 // userViewerCmp.populate(true, false);
308 // userViewerCmp.setLayoutData(EclipseUiUtils.fillAll());
309 //
310 // // Controllers
311 // TableViewer userViewer = userViewerCmp.getTableViewer();
312 // userViewer.addDoubleClickListener(new
313 // UserTableDefaultDClickListener(partService));
314 // int operations = DND.DROP_COPY | DND.DROP_MOVE;
315 // Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
316 // userViewer.addDropSupport(operations, tt,
317 // new GroupDropListener(userAdminWrapper, userViewerCmp, (Group)
318 // getDisplayedUser()));
319 //
320 // // userViewerCmp.refresh();
321 // return userViewerCmp;
322 // }
323
324 // Local viewers
325 private class MyUserTableViewer extends LdifUsersTable {
326 private static final long serialVersionUID = 8467999509931900367L;
327
328 private final UserFilter userFilter;
329
330 public MyUserTableViewer(Composite parent, int style, UserAdmin userAdmin) {
331 super(parent, style, true);
332 userFilter = new UserFilter();
333
334 }
335
336 @Override
337 protected List<User> listFilteredElements(String filter) {
338 // reload user and set it in the editor
339 Group group = (Group) getDisplayedUser();
340 Role[] roles = group.getMembers();
341 List<User> users = new ArrayList<User>();
342 userFilter.setSearchText(filter);
343 // userFilter.setShowSystemRole(true);
344 for (Role role : roles)
345 // if (role.getType() == Role.GROUP)
346 if (userFilter.select(null, null, role))
347 users.add((User) role);
348 return users;
349 }
350 }
351
352 // private void addRemoveAbility(ToolBarManager toolBarManager, TableViewer
353 // userViewer, Group group) {
354 // // Section section = sectionPart.getSection();
355 // // ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
356 // // ToolBar toolbar = toolBarManager.createControl(parent);
357 // // ToolBar toolbar = toolBarManager.getControl();
358 // // final Cursor handCursor = new Cursor(toolbar.getDisplay(),
359 // SWT.CURSOR_HAND);
360 // // toolbar.setCursor(handCursor);
361 // // toolbar.addDisposeListener(new DisposeListener() {
362 // // private static final long serialVersionUID = 3882131405820522925L;
363 // //
364 // // public void widgetDisposed(DisposeEvent e) {
365 // // if ((handCursor != null) && (handCursor.isDisposed() == false)) {
366 // // handCursor.dispose();
367 // // }
368 // // }
369 // // });
370 //
371 // Action action = new RemoveMembershipAction(userViewer, group, "Remove
372 // selected items from this group",
373 // SecurityAdminImages.ICON_REMOVE_DESC);
374 // toolBarManager.add(action);
375 // toolBarManager.update(true);
376 // // section.setTextClient(toolbar);
377 // }
378
379 private class RemoveMembershipAction extends Action {
380 private static final long serialVersionUID = -1337713097184522588L;
381
382 private final TableViewer userViewer;
383 private final Group group;
384
385 RemoveMembershipAction(TableViewer userViewer, Group group, String name, ImageDescriptor img) {
386 super(name, img);
387 this.userViewer = userViewer;
388 this.group = group;
389 }
390
391 @Override
392 public void run() {
393 ISelection selection = userViewer.getSelection();
394 if (selection.isEmpty())
395 return;
396
397 @SuppressWarnings("unchecked")
398 Iterator<User> it = ((IStructuredSelection) selection).iterator();
399 List<User> users = new ArrayList<User>();
400 while (it.hasNext()) {
401 User currUser = it.next();
402 users.add(currUser);
403 }
404
405 userAdminWrapper.beginTransactionIfNeeded();
406 for (User user : users) {
407 group.removeMember(user);
408 }
409 userAdminWrapper.commitOrNotifyTransactionStateChange();
410 userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group));
411 }
412 }
413
414 // LOCAL CONTROLLERS
415 private class GroupMembersPart extends AbstractFormPart {
416 private final LdifUsersTable userViewer;
417 // private final Group group;
418
419 private GroupChangeListener listener;
420
421 public GroupMembersPart(LdifUsersTable userViewer) {
422 // super(section);
423 this.userViewer = userViewer;
424 // this.group = group;
425 }
426
427 @Override
428 public void initialize(IManagedForm form) {
429 super.initialize(form);
430 listener = new GroupChangeListener(userViewer.getDisplay(), GroupMembersPart.this);
431 userAdminWrapper.addListener(listener);
432 }
433
434 @Override
435 public void dispose() {
436 userAdminWrapper.removeListener(listener);
437 super.dispose();
438 }
439
440 @Override
441 public void refresh() {
442 userViewer.refresh();
443 super.refresh();
444 }
445 }
446
447 /**
448 * Defines this table as being a potential target to add group membership
449 * (roles) to this group
450 */
451 private class GroupDropListener extends ViewerDropAdapter {
452 private static final long serialVersionUID = 2893468717831451621L;
453
454 private final UserAdminWrapper userAdminWrapper;
455 // private final LdifUsersTable myUserViewerCmp;
456 private final Group myGroup;
457
458 public GroupDropListener(UserAdminWrapper userAdminWrapper, LdifUsersTable userTableViewerCmp, Group group) {
459 super(userTableViewerCmp.getTableViewer());
460 this.userAdminWrapper = userAdminWrapper;
461 this.myGroup = group;
462 // this.myUserViewerCmp = userTableViewerCmp;
463 }
464
465 @Override
466 public boolean validateDrop(Object target, int operation, TransferData transferType) {
467 // Target is always OK in a list only view
468 // TODO check if not a string
469 boolean validDrop = true;
470 return validDrop;
471 }
472
473 @Override
474 public void drop(DropTargetEvent event) {
475 // TODO Is there an opportunity to perform the check before?
476 String newUserName = (String) event.data;
477 UserAdmin myUserAdmin = userAdminWrapper.getUserAdmin();
478 Role role = myUserAdmin.getRole(newUserName);
479 if (role.getType() == Role.GROUP) {
480 Group newGroup = (Group) role;
481 Shell shell = getViewer().getControl().getShell();
482 // Sanity checks
483 if (myGroup == newGroup) { // Equality
484 MessageDialog.openError(shell, "Forbidden addition ", "A group cannot be a member of itself.");
485 return;
486 }
487
488 // Cycle
489 String myName = myGroup.getName();
490 List<User> myMemberships = getFlatGroups(myGroup);
491 if (myMemberships.contains(newGroup)) {
492 MessageDialog.openError(shell, "Forbidden addition: cycle",
493 "Cannot add " + newUserName + " to group " + myName + ". This would create a cycle");
494 return;
495 }
496
497 // Already member
498 List<User> newGroupMemberships = getFlatGroups(newGroup);
499 if (newGroupMemberships.contains(myGroup)) {
500 MessageDialog.openError(shell, "Forbidden addition",
501 "Cannot add " + newUserName + " to group " + myName + ", this membership already exists");
502 return;
503 }
504 userAdminWrapper.beginTransactionIfNeeded();
505 myGroup.addMember(newGroup);
506 userAdminWrapper.commitOrNotifyTransactionStateChange();
507 userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, myGroup));
508 } else if (role.getType() == Role.USER) {
509 // TODO check if the group is already member of this group
510 WorkTransaction transaction = userAdminWrapper.beginTransactionIfNeeded();
511 User user = (User) role;
512 myGroup.addMember(user);
513 if (UserAdminWrapper.COMMIT_ON_SAVE)
514 try {
515 transaction.commit();
516 } catch (Exception e) {
517 throw new IllegalStateException(
518 "Cannot commit transaction " + "after user group membership update", e);
519 }
520 userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, myGroup));
521 }
522 super.drop(event);
523 }
524
525 @Override
526 public boolean performDrop(Object data) {
527 // myUserViewerCmp.refresh();
528 return true;
529 }
530 }
531
532 // LOCAL HELPERS
533 // private Composite addSection(FormToolkit tk, Composite parent) {
534 // Section section = tk.createSection(parent, SWT.NO_FOCUS);
535 // section.setLayoutData(EclipseUiUtils.fillWidth());
536 // Composite body = tk.createComposite(section, SWT.WRAP);
537 // body.setLayoutData(EclipseUiUtils.fillAll());
538 // section.setClient(body);
539 // return body;
540 // }
541
542 /** Creates label and text. */
543 // private Text createLT(Composite parent, String label, String value) {
544 // FormToolkit toolkit = getManagedForm().getToolkit();
545 // Label lbl = toolkit.createLabel(parent, label);
546 // lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
547 // lbl.setFont(EclipseUiUtils.getBoldFont(parent));
548 // Text text = toolkit.createText(parent, value, SWT.BORDER);
549 // text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
550 // CmsUiUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT);
551 // return text;
552 // }
553 //
554 // Text createReadOnlyLT(Composite parent, String label, String value) {
555 // FormToolkit toolkit = getManagedForm().getToolkit();
556 // Label lbl = toolkit.createLabel(parent, label);
557 // lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
558 // lbl.setFont(EclipseUiUtils.getBoldFont(parent));
559 // Text text = toolkit.createText(parent, value, SWT.NONE);
560 // text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
561 // text.setEditable(false);
562 // CmsUiUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT);
563 // return text;
564 // }
565
566 }