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