1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.console.topology;
20
21 import com.fasterxml.jackson.databind.json.JsonMapper;
22 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
23 import java.io.Serializable;
24 import java.text.MessageFormat;
25 import java.util.Optional;
26 import org.apache.syncope.client.console.SyncopeConsoleSession;
27 import org.apache.syncope.client.console.audit.AuditHistoryModal;
28 import org.apache.syncope.client.console.panels.ConnObjects;
29 import org.apache.syncope.client.console.panels.TogglePanel;
30 import org.apache.syncope.client.console.rest.AuditRestClient;
31 import org.apache.syncope.client.console.rest.ConnectorRestClient;
32 import org.apache.syncope.client.console.rest.ResourceRestClient;
33 import org.apache.syncope.client.console.status.ResourceStatusModal;
34 import org.apache.syncope.client.console.tasks.PropagationTasks;
35 import org.apache.syncope.client.console.tasks.PullTasks;
36 import org.apache.syncope.client.console.tasks.PushTasks;
37 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
38 import org.apache.syncope.client.console.wicket.markup.html.form.IndicatingOnConfirmAjaxLink;
39 import org.apache.syncope.client.console.wizards.resources.ConnectorWizardBuilder;
40 import org.apache.syncope.client.console.wizards.resources.ResourceProvision;
41 import org.apache.syncope.client.console.wizards.resources.ResourceProvisionPanel;
42 import org.apache.syncope.client.console.wizards.resources.ResourceWizardBuilder;
43 import org.apache.syncope.client.ui.commons.Constants;
44 import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
45 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
46 import org.apache.syncope.common.lib.SyncopeClientException;
47 import org.apache.syncope.common.lib.to.ConnInstanceTO;
48 import org.apache.syncope.common.lib.to.Provision;
49 import org.apache.syncope.common.lib.to.ResourceTO;
50 import org.apache.syncope.common.lib.types.AuditElements;
51 import org.apache.syncope.common.lib.types.IdMEntitlement;
52 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
53 import org.apache.wicket.PageReference;
54 import org.apache.wicket.ajax.AjaxRequestTarget;
55 import org.apache.wicket.ajax.markup.html.AjaxLink;
56 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
57 import org.apache.wicket.event.Broadcast;
58 import org.apache.wicket.event.IEvent;
59 import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
60 import org.apache.wicket.markup.html.WebMarkupContainer;
61 import org.apache.wicket.markup.html.panel.Fragment;
62 import org.apache.wicket.model.CompoundPropertyModel;
63 import org.apache.wicket.model.IModel;
64 import org.apache.wicket.model.Model;
65 import org.apache.wicket.model.StringResourceModel;
66 import org.apache.wicket.spring.injection.annot.SpringBean;
67
68 public class TopologyTogglePanel extends TogglePanel<Serializable> {
69
70 private static final long serialVersionUID = -2025535531121434056L;
71
72 protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
73
74 @SpringBean
75 protected ConnectorRestClient connectorRestClient;
76
77 @SpringBean
78 protected ResourceRestClient resourceRestClient;
79
80 @SpringBean
81 protected AuditRestClient auditRestClient;
82
83 protected final WebMarkupContainer container;
84
85 protected final BaseModal<Serializable> propTaskModal;
86
87 protected final BaseModal<Serializable> schedTaskModal;
88
89 protected final BaseModal<Serializable> provisionModal;
90
91 protected final BaseModal<Serializable> historyModal;
92
93 public TopologyTogglePanel(final String id, final PageReference pageRef) {
94 super(id, "topologyTogglePanel", pageRef);
95
96 modal.size(Modal.Size.Large);
97 setFooterVisibility(false);
98
99 propTaskModal = new BaseModal<>(Constants.OUTER);
100 propTaskModal.size(Modal.Size.Large);
101 addOuterObject(propTaskModal);
102
103 schedTaskModal = new BaseModal<>(Constants.OUTER) {
104
105 private static final long serialVersionUID = 389935548143327858L;
106
107 @Override
108 protected void onConfigure() {
109 super.onConfigure();
110 setFooterVisible(false);
111 }
112 };
113 schedTaskModal.size(Modal.Size.Large);
114 addOuterObject(schedTaskModal);
115
116 provisionModal = new BaseModal<>(Constants.OUTER);
117 provisionModal.size(Modal.Size.Large);
118 provisionModal.addSubmitButton();
119 addOuterObject(provisionModal);
120
121 historyModal = new BaseModal<>(Constants.OUTER);
122 historyModal.size(Modal.Size.Large);
123 addOuterObject(historyModal);
124
125 container = new WebMarkupContainer("container");
126 container.setOutputMarkupPlaceholderTag(true);
127 addInnerObject(container);
128
129 container.add(getEmptyFragment());
130 }
131
132 public void toggleWithContent(final AjaxRequestTarget target, final TopologyNode node) {
133 setHeader(target, node.getDisplayName());
134
135 modal.setWindowClosedCallback(t -> {
136 modal.show(false);
137 send(pageRef.getPage(), Broadcast.DEPTH, new UpdateEvent(node.getKey(), t));
138 });
139
140 switch (node.getKind()) {
141 case SYNCOPE:
142 container.addOrReplace(getSyncopeFragment(pageRef));
143 break;
144 case CONNECTOR_SERVER:
145 container.addOrReplace(getLocationFragment(node, pageRef));
146 break;
147 case FS_PATH:
148 container.addOrReplace(getLocationFragment(node, pageRef));
149 break;
150 case CONNECTOR:
151 container.addOrReplace(getConnectorFragment(node, pageRef));
152 break;
153 case RESOURCE:
154 container.addOrReplace(getResourceFragment(node, pageRef));
155 break;
156 default:
157 container.addOrReplace(getEmptyFragment());
158 }
159
160 target.add(container);
161
162 toggle(target, node, true);
163 }
164
165 @Override
166 protected String getTargetKey(final Serializable modelObject) {
167 String key = super.getTargetKey(modelObject);
168 if (modelObject instanceof ResourceProvision) {
169 key = ((ResourceProvision) modelObject).getKey();
170 } else if (modelObject instanceof TopologyNode) {
171 key = ((TopologyNode) modelObject).getKey();
172 }
173 return key;
174 }
175
176 private Fragment getEmptyFragment() {
177 return new Fragment("actions", "emptyFragment", this);
178 }
179
180 private Fragment getSyncopeFragment(final PageReference pageRef) {
181 Fragment fragment = new Fragment("actions", "syncopeActions", this);
182
183 AjaxLink<String> reload = new IndicatingOnConfirmAjaxLink<>("reload", "connectors.confirm.reload", true) {
184
185 private static final long serialVersionUID = -2075933173666007020L;
186
187 @Override
188 public void onClick(final AjaxRequestTarget target) {
189 try {
190 connectorRestClient.reload();
191 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
192 } catch (Exception e) {
193 LOG.error("While reloading all connectors", e);
194 SyncopeConsoleSession.get().onException(e);
195 }
196 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
197 }
198 };
199 fragment.add(reload);
200 MetaDataRoleAuthorizationStrategy.authorize(reload, RENDER, IdMEntitlement.CONNECTOR_RELOAD);
201
202 return fragment;
203 }
204
205 private Fragment getLocationFragment(final TopologyNode node, final PageReference pageRef) {
206 Fragment fragment = new Fragment("actions", "locationActions", this);
207
208 AjaxLink<String> create = new IndicatingAjaxLink<>("create") {
209
210 private static final long serialVersionUID = 3776750333491622263L;
211
212 @Override
213 public void onClick(final AjaxRequestTarget target) {
214 final ConnInstanceTO modelObject = new ConnInstanceTO();
215 modelObject.setLocation(node.getKey());
216
217 final IModel<ConnInstanceTO> model = new CompoundPropertyModel<>(modelObject);
218 modal.setFormModel(model);
219
220 target.add(modal.setContent(new ConnectorWizardBuilder(modelObject, connectorRestClient, pageRef).
221 build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
222
223 modal.header(new Model<>(MessageFormat.format(getString("connector.new"), node.getKey())));
224 modal.show(true);
225 }
226
227 @Override
228 public String getAjaxIndicatorMarkupId() {
229 return Constants.VEIL_INDICATOR_MARKUP_ID;
230 }
231 };
232 fragment.add(create);
233 MetaDataRoleAuthorizationStrategy.authorize(create, RENDER, IdMEntitlement.CONNECTOR_CREATE);
234
235 return fragment;
236 }
237
238 private Fragment getConnectorFragment(final TopologyNode node, final PageReference pageRef) {
239 Fragment fragment = new Fragment("actions", "connectorActions", this);
240
241 AjaxLink<String> delete = new IndicatingOnConfirmAjaxLink<>("delete", Constants.CONFIRM_DELETE, true) {
242
243 private static final long serialVersionUID = 3776750333491622263L;
244
245 @Override
246 public void onClick(final AjaxRequestTarget target) {
247 try {
248 connectorRestClient.delete(String.class.cast(node.getKey()));
249 target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
250 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
251 toggle(target, false);
252 } catch (SyncopeClientException e) {
253 LOG.error("While deleting resource {}", node.getKey(), e);
254 SyncopeConsoleSession.get().onException(e);
255 }
256 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
257 }
258 };
259 MetaDataRoleAuthorizationStrategy.authorize(delete, RENDER, IdMEntitlement.CONNECTOR_DELETE);
260 fragment.add(delete);
261
262 AjaxLink<String> create = new IndicatingAjaxLink<>("create") {
263
264 private static final long serialVersionUID = 3776750333491622263L;
265
266 @Override
267 public void onClick(final AjaxRequestTarget target) {
268 final ResourceTO modelObject = new ResourceTO();
269 modelObject.setConnector(String.class.cast(node.getKey()));
270 modelObject.setConnectorDisplayName(node.getDisplayName());
271
272 final IModel<ResourceTO> model = new CompoundPropertyModel<>(modelObject);
273 modal.setFormModel(model);
274
275 target.add(modal.setContent(new ResourceWizardBuilder(
276 modelObject, resourceRestClient, connectorRestClient, pageRef).
277 build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
278
279 modal.header(new Model<>(MessageFormat.format(getString("resource.new"), node.getKey())));
280 modal.show(true);
281 }
282
283 @Override
284 public String getAjaxIndicatorMarkupId() {
285 return Constants.VEIL_INDICATOR_MARKUP_ID;
286 }
287
288 };
289 MetaDataRoleAuthorizationStrategy.authorize(create, RENDER, IdMEntitlement.RESOURCE_CREATE);
290 fragment.add(create);
291
292 AjaxLink<String> edit = new IndicatingAjaxLink<>("edit") {
293
294 private static final long serialVersionUID = 3776750333491622263L;
295
296 @Override
297 public void onClick(final AjaxRequestTarget target) {
298 ConnInstanceTO connInstance = connectorRestClient.read(String.class.cast(node.getKey()));
299
300 final IModel<ConnInstanceTO> model = new CompoundPropertyModel<>(connInstance);
301 modal.setFormModel(model);
302
303 target.add(modal.setContent(new ConnectorWizardBuilder(connInstance, connectorRestClient, pageRef).
304 build(BaseModal.CONTENT_ID,
305 SyncopeConsoleSession.get().
306 owns(IdMEntitlement.CONNECTOR_UPDATE, connInstance.getAdminRealm())
307 ? AjaxWizard.Mode.EDIT
308 : AjaxWizard.Mode.READONLY)));
309
310 modal.header(
311 new Model<>(MessageFormat.format(getString("connector.edit"), connInstance.getDisplayName())));
312 modal.show(true);
313 }
314
315 @Override
316 public String getAjaxIndicatorMarkupId() {
317 return Constants.VEIL_INDICATOR_MARKUP_ID;
318 }
319 };
320 MetaDataRoleAuthorizationStrategy.authorize(edit, RENDER, IdMEntitlement.CONNECTOR_READ);
321 fragment.add(edit);
322
323 AjaxLink<String> history = new IndicatingAjaxLink<>("history") {
324
325 private static final long serialVersionUID = -1876519166660008562L;
326
327 @Override
328 public void onClick(final AjaxRequestTarget target) {
329 ConnInstanceTO modelObject = connectorRestClient.read(node.getKey());
330
331 target.add(historyModal.setContent(new AuditHistoryModal<>(
332 AuditElements.EventCategoryType.LOGIC,
333 "ConnectorLogic",
334 modelObject,
335 IdMEntitlement.CONNECTOR_UPDATE,
336 auditRestClient) {
337
338 private static final long serialVersionUID = -3225348282675513648L;
339
340 @Override
341 protected void restore(final String json, final AjaxRequestTarget target) {
342 try {
343 ConnInstanceTO updated = MAPPER.readValue(json, ConnInstanceTO.class);
344 connectorRestClient.update(updated);
345
346 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
347 toggle(target, false);
348 } catch (Exception e) {
349 LOG.error("While restoring connector {}", node.getKey(), e);
350 SyncopeConsoleSession.get().onException(e);
351 }
352 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
353 }
354 }));
355
356 historyModal.header(
357 new Model<>(MessageFormat.format(getString("connector.menu.history"), node.getDisplayName())));
358
359 historyModal.show(true);
360 }
361
362 @Override
363 public String getAjaxIndicatorMarkupId() {
364 return Constants.VEIL_INDICATOR_MARKUP_ID;
365 }
366 };
367 MetaDataRoleAuthorizationStrategy.authorize(history, RENDER,
368 String.format("%s,%s", IdMEntitlement.CONNECTOR_READ, IdRepoEntitlement.AUDIT_LIST));
369 fragment.add(history);
370
371 return fragment;
372 }
373
374 private Fragment getResourceFragment(final TopologyNode node, final PageReference pageRef) {
375 Fragment fragment = new Fragment("actions", "resourceActions", this);
376
377 AjaxLink<String> delete = new IndicatingOnConfirmAjaxLink<>("delete", Constants.CONFIRM_DELETE, true) {
378
379 private static final long serialVersionUID = 3776750333491622263L;
380
381 @Override
382 public void onClick(final AjaxRequestTarget target) {
383 try {
384 resourceRestClient.delete(node.getKey());
385 target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
386 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
387 toggle(target, false);
388 } catch (SyncopeClientException e) {
389 LOG.error("While deleting resource {}", node.getKey(), e);
390 SyncopeConsoleSession.get().onException(e);
391 }
392 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
393 }
394 };
395 MetaDataRoleAuthorizationStrategy.authorize(delete, RENDER, IdMEntitlement.RESOURCE_DELETE);
396 fragment.add(delete);
397
398 AjaxLink<String> edit = new IndicatingAjaxLink<>("edit") {
399
400 private static final long serialVersionUID = 3776750333491622263L;
401
402 @Override
403 public void onClick(final AjaxRequestTarget target) {
404 ResourceTO resource = resourceRestClient.read(node.getKey());
405 ConnInstanceTO connInstance = connectorRestClient.read(resource.getConnector());
406
407 IModel<ResourceTO> model = new CompoundPropertyModel<>(resource);
408 modal.setFormModel(model);
409
410 target.add(modal.setContent(new ResourceWizardBuilder(
411 resource, resourceRestClient, connectorRestClient, pageRef).
412 build(BaseModal.CONTENT_ID,
413 SyncopeConsoleSession.get().
414 owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())
415 ? AjaxWizard.Mode.EDIT
416 : AjaxWizard.Mode.READONLY)));
417
418 modal.header(new Model<>(MessageFormat.format(getString("resource.edit"), node.getKey())));
419 modal.show(true);
420 }
421
422 @Override
423 public String getAjaxIndicatorMarkupId() {
424 return Constants.VEIL_INDICATOR_MARKUP_ID;
425 }
426 };
427 MetaDataRoleAuthorizationStrategy.authorize(edit, RENDER, IdMEntitlement.RESOURCE_READ);
428 fragment.add(edit);
429
430 AjaxLink<String> status = new IndicatingAjaxLink<>("reconciliation") {
431
432 private static final long serialVersionUID = 3776750333491622263L;
433
434 @Override
435 public void onClick(final AjaxRequestTarget target) {
436 ResourceTO modelObject = resourceRestClient.read(node.getKey());
437 target.add(propTaskModal.setContent(new ResourceStatusModal(pageRef, modelObject)));
438 propTaskModal.header(
439 new Model<>(MessageFormat.format(getString("resource.reconciliation"), node.getKey())));
440 propTaskModal.show(true);
441 }
442
443 @Override
444 public String getAjaxIndicatorMarkupId() {
445 return Constants.VEIL_INDICATOR_MARKUP_ID;
446 }
447 };
448 MetaDataRoleAuthorizationStrategy.authorize(status, RENDER, IdRepoEntitlement.USER_UPDATE);
449 fragment.add(status);
450
451 AjaxLink<String> provision = new IndicatingAjaxLink<>("provision") {
452
453 private static final long serialVersionUID = 3776750333491622263L;
454
455 @Override
456 public void onClick(final AjaxRequestTarget target) {
457 ResourceTO resource = resourceRestClient.read(node.getKey());
458 ConnInstanceTO connInstance = connectorRestClient.read(resource.getConnector());
459
460 if (SyncopeConsoleSession.get().
461 owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())) {
462
463 provisionModal.addSubmitButton();
464 } else {
465 provisionModal.removeSubmitButton();
466 }
467
468 IModel<ResourceTO> model = new CompoundPropertyModel<>(resource);
469 provisionModal.setFormModel(model);
470
471 target.add(provisionModal.setContent(
472 new ResourceProvisionPanel(provisionModal, resource, connInstance.getAdminRealm(), pageRef)));
473
474 provisionModal.header(new Model<>(MessageFormat.format(getString("resource.edit"), node.getKey())));
475 provisionModal.show(true);
476 }
477
478 @Override
479 public String getAjaxIndicatorMarkupId() {
480 return Constants.VEIL_INDICATOR_MARKUP_ID;
481 }
482 };
483 MetaDataRoleAuthorizationStrategy.authorize(edit, RENDER, IdMEntitlement.RESOURCE_READ);
484 fragment.add(provision);
485
486 AjaxLink<String> explore = new IndicatingAjaxLink<>("explore") {
487
488 private static final long serialVersionUID = 3776750333491622263L;
489
490 @Override
491 public void onClick(final AjaxRequestTarget target) {
492 ResourceTO resource = resourceRestClient.read(node.getKey());
493
494 target.add(propTaskModal.setContent(new ConnObjects(resource, pageRef)));
495 propTaskModal.header(new StringResourceModel("resource.explore.list", Model.of(node)));
496 propTaskModal.show(true);
497 }
498
499 @Override
500 public String getAjaxIndicatorMarkupId() {
501 return Constants.VEIL_INDICATOR_MARKUP_ID;
502 }
503 };
504 MetaDataRoleAuthorizationStrategy.authorize(explore, RENDER, IdMEntitlement.RESOURCE_LIST_CONNOBJECT);
505 fragment.add(explore);
506
507 AjaxLink<String> propagation = new IndicatingAjaxLink<>("propagation") {
508
509 private static final long serialVersionUID = 3776750333491622263L;
510
511 @Override
512 @SuppressWarnings("unchecked")
513 public void onClick(final AjaxRequestTarget target) {
514 target.add(propTaskModal.setContent(
515 new PropagationTasks(propTaskModal, node.getKey(), pageRef)));
516 propTaskModal.header(
517 new Model<>(MessageFormat.format(getString("task.propagation.list"), node.getKey())));
518 propTaskModal.show(true);
519 }
520
521 @Override
522 public String getAjaxIndicatorMarkupId() {
523 return Constants.VEIL_INDICATOR_MARKUP_ID;
524 }
525 };
526 MetaDataRoleAuthorizationStrategy.authorize(propagation, RENDER, IdRepoEntitlement.TASK_LIST);
527 fragment.add(propagation);
528
529 AjaxLink<String> pull = new IndicatingAjaxLink<>("pull") {
530
531 private static final long serialVersionUID = 3776750333491622263L;
532
533 @Override
534 public void onClick(final AjaxRequestTarget target) {
535 target.add(schedTaskModal.setContent(new PullTasks(schedTaskModal, node.getKey(), pageRef)));
536 schedTaskModal.header(new Model<>(MessageFormat.format(getString("task.pull.list"), node.getKey())));
537 schedTaskModal.show(true);
538 }
539
540 @Override
541 public String getAjaxIndicatorMarkupId() {
542 return Constants.VEIL_INDICATOR_MARKUP_ID;
543 }
544 };
545 MetaDataRoleAuthorizationStrategy.authorize(pull, RENDER, IdRepoEntitlement.TASK_LIST);
546 fragment.add(pull);
547
548 AjaxLink<String> push = new IndicatingAjaxLink<>("push") {
549
550 private static final long serialVersionUID = 3776750333491622263L;
551
552 @Override
553 public void onClick(final AjaxRequestTarget target) {
554 target.add(schedTaskModal.setContent(new PushTasks(schedTaskModal, node.getKey(), pageRef)));
555 schedTaskModal.header(new Model<>(MessageFormat.format(getString("task.push.list"), node.getKey())));
556 schedTaskModal.show(true);
557 }
558
559 @Override
560 public String getAjaxIndicatorMarkupId() {
561 return Constants.VEIL_INDICATOR_MARKUP_ID;
562 }
563 };
564 MetaDataRoleAuthorizationStrategy.authorize(push, RENDER, IdRepoEntitlement.TASK_LIST);
565 fragment.add(push);
566
567 AjaxLink<String> history = new IndicatingAjaxLink<>("history") {
568
569 private static final long serialVersionUID = -1876519166660008562L;
570
571 @Override
572 public void onClick(final AjaxRequestTarget target) {
573 ResourceTO modelObject = resourceRestClient.read(node.getKey());
574
575 target.add(historyModal.setContent(new AuditHistoryModal<>(
576 AuditElements.EventCategoryType.LOGIC,
577 "ResourceLogic",
578 modelObject,
579 IdMEntitlement.RESOURCE_UPDATE,
580 auditRestClient) {
581
582 private static final long serialVersionUID = -3712506022627033811L;
583
584 @Override
585 protected void restore(final String json, final AjaxRequestTarget target) {
586 try {
587 ResourceTO updated = MAPPER.readValue(json, ResourceTO.class);
588 resourceRestClient.update(updated);
589
590 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
591 toggle(target, false);
592 } catch (Exception e) {
593 LOG.error("While restoring resource {}", node.getKey(), e);
594 SyncopeConsoleSession.get().onException(e);
595 }
596 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
597 }
598 }));
599
600 historyModal.header(
601 new Model<>(MessageFormat.format(getString("resource.menu.history"), node.getDisplayName())));
602
603 historyModal.show(true);
604 }
605
606 @Override
607 public String getAjaxIndicatorMarkupId() {
608 return Constants.VEIL_INDICATOR_MARKUP_ID;
609 }
610 };
611 MetaDataRoleAuthorizationStrategy.authorize(history, RENDER,
612 String.format("%s,%s", IdMEntitlement.RESOURCE_READ, IdRepoEntitlement.AUDIT_LIST));
613 fragment.add(history);
614
615
616 AjaxLink<String> clone = new IndicatingAjaxLink<>("clone") {
617
618 private static final long serialVersionUID = -7978723352517770644L;
619
620 @Override
621 public void onClick(final AjaxRequestTarget target) {
622 try {
623 ResourceTO resource = resourceRestClient.read(node.getKey());
624 resource.setKey("Copy of " + node.getKey());
625
626 for (Provision provision : resource.getProvisions()) {
627 if (provision.getMapping() != null) {
628 provision.getMapping().getLinkingItems().clear();
629 }
630 provision.getVirSchemas().clear();
631 }
632 target.add(modal.setContent(new ResourceWizardBuilder(
633 resource, resourceRestClient, connectorRestClient, pageRef).
634 build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
635
636 modal.header(new Model<>(MessageFormat.format(getString("resource.clone"), node.getKey())));
637 modal.show(true);
638
639 } catch (SyncopeClientException e) {
640 LOG.error("While cloning resource {}", node.getKey(), e);
641 SyncopeConsoleSession.get().onException(e);
642 }
643 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
644 }
645
646 };
647 MetaDataRoleAuthorizationStrategy.authorize(clone, RENDER, IdMEntitlement.RESOURCE_CREATE);
648 fragment.add(clone);
649
650 return fragment;
651 }
652
653 @Override
654 public void onEvent(final IEvent<?> event) {
655 super.onEvent(event);
656
657 if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
658 AjaxWizard.NewItemFinishEvent<?> item = AjaxWizard.NewItemFinishEvent.class.cast(event.getPayload());
659 Serializable result = item.getResult();
660 Optional<AjaxRequestTarget> target = item.getTarget();
661 if (result instanceof ConnInstanceTO) {
662
663 target.ifPresent(t -> setHeader(t, ConnInstanceTO.class.cast(result).getDisplayName()));
664 }
665 }
666 }
667
668 public static final class UpdateEvent {
669
670 private final AjaxRequestTarget target;
671
672 private final String key;
673
674 public UpdateEvent(final String key, final AjaxRequestTarget target) {
675 this.target = target;
676 this.key = key;
677 }
678
679 public AjaxRequestTarget getTarget() {
680 return target;
681 }
682
683 public String getKey() {
684 return key;
685 }
686 }
687 }