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.panels;
20
21 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
22 import java.io.Serializable;
23 import java.text.MessageFormat;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.syncope.client.console.SyncopeConsoleSession;
30 import org.apache.syncope.client.console.audit.AuditHistoryModal;
31 import org.apache.syncope.client.console.commons.IdRepoConstants;
32 import org.apache.syncope.client.console.commons.ResourceDataProvider;
33 import org.apache.syncope.client.console.pages.BasePage;
34 import org.apache.syncope.client.console.rest.AuditRestClient;
35 import org.apache.syncope.client.console.rest.ConnectorRestClient;
36 import org.apache.syncope.client.console.rest.ResourceRestClient;
37 import org.apache.syncope.client.console.status.ResourceStatusModal;
38 import org.apache.syncope.client.console.tasks.PropagationTasks;
39 import org.apache.syncope.client.console.tasks.PullTasks;
40 import org.apache.syncope.client.console.tasks.PushTasks;
41 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
42 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
43 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
44 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
45 import org.apache.syncope.client.console.wizards.resources.ResourceProvisionPanel;
46 import org.apache.syncope.client.console.wizards.resources.ResourceWizardBuilder;
47 import org.apache.syncope.client.ui.commons.Constants;
48 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
49 import org.apache.syncope.common.lib.SyncopeClientException;
50 import org.apache.syncope.common.lib.to.ConnInstanceTO;
51 import org.apache.syncope.common.lib.to.ResourceTO;
52 import org.apache.syncope.common.lib.types.AuditElements;
53 import org.apache.syncope.common.lib.types.IdMEntitlement;
54 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
55 import org.apache.wicket.PageReference;
56 import org.apache.wicket.ajax.AjaxRequestTarget;
57 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
58 import org.apache.wicket.event.IEvent;
59 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
60 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
61 import org.apache.wicket.model.CompoundPropertyModel;
62 import org.apache.wicket.model.IModel;
63 import org.apache.wicket.model.Model;
64 import org.apache.wicket.model.ResourceModel;
65 import org.apache.wicket.model.StringResourceModel;
66 import org.apache.wicket.spring.injection.annot.SpringBean;
67
68 public class ResourceDirectoryPanel extends
69 DirectoryPanel<Serializable, Serializable, ResourceDataProvider, ResourceRestClient> {
70
71 private static final long serialVersionUID = -5223129956783782225L;
72
73 @SpringBean
74 protected ConnectorRestClient connectorRestClient;
75
76 @SpringBean
77 protected AuditRestClient auditRestClient;
78
79 protected String keyword;
80
81 protected final BaseModal<Serializable> propTaskModal;
82
83 protected final BaseModal<Serializable> schedTaskModal;
84
85 protected final BaseModal<Serializable> provisionModal;
86
87 protected final BaseModal<Serializable> historyModal;
88
89 protected ResourceDirectoryPanel(final String id, final ResourceDirectoryPanel.Builder builder) {
90 super(id, builder);
91
92 if (SyncopeConsoleSession.get().owns("RESOURCE_CREATE")) {
93 MetaDataRoleAuthorizationStrategy.authorizeAll(addAjaxLink, RENDER);
94 } else {
95 MetaDataRoleAuthorizationStrategy.unauthorizeAll(addAjaxLink, RENDER);
96 }
97
98 setShowResultPanel(false);
99 modal.size(Modal.Size.Large);
100 initResultTable();
101
102 restClient = builder.restClient;
103
104 propTaskModal = new BaseModal<>(Constants.OUTER);
105 propTaskModal.size(Modal.Size.Large);
106 addOuterObject(propTaskModal);
107
108 schedTaskModal = new BaseModal<>(Constants.OUTER) {
109
110 private static final long serialVersionUID = -6165152045136958913L;
111
112 @Override
113 protected void onConfigure() {
114 super.onConfigure();
115 setFooterVisible(false);
116 }
117 };
118 schedTaskModal.size(Modal.Size.Large);
119 addOuterObject(schedTaskModal);
120
121 provisionModal = new BaseModal<>(Constants.OUTER);
122 provisionModal.size(Modal.Size.Large);
123 provisionModal.addSubmitButton();
124 addOuterObject(provisionModal);
125
126 historyModal = new BaseModal<>(Constants.OUTER);
127 historyModal.size(Modal.Size.Large);
128 addOuterObject(historyModal);
129 }
130
131 @Override
132 public void onEvent(final IEvent<?> event) {
133 if (event.getPayload() instanceof ResourceSearchEvent) {
134 ResourceSearchEvent payload = (ResourceSearchEvent) event.getPayload();
135 AjaxRequestTarget target = payload.getTarget();
136 if (StringUtils.isNotEmpty(payload.getKeyword())) {
137 keyword = payload.getKeyword().toLowerCase();
138 }
139 updateResultTable(target);
140 } else {
141 super.onEvent(event);
142 }
143 }
144
145 @Override
146 protected ResourceDataProvider dataProvider() {
147 dataProvider = new ResourceDataProvider(restClient, rows, pageRef, keyword);
148 return dataProvider;
149 }
150
151 public ResourceDataProvider getDataProvider() {
152 return dataProvider;
153 }
154
155 @Override
156 protected String paginatorRowsKey() {
157 return IdRepoConstants.PREF_PARAMETERS_PAGINATOR_ROWS;
158 }
159
160 @Override
161 protected List<IColumn<Serializable, String>> getColumns() {
162 final List<IColumn<Serializable, String>> columns = new ArrayList<>();
163 columns.add(new PropertyColumn<>(
164 new ResourceModel("key"), "keySortParam", "key"));
165 columns.add(new PropertyColumn<>(
166 new ResourceModel("connectorDisplayName"), "connectorDisplayNameSortParam", "connectorDisplayName"));
167 return columns;
168 }
169
170 @Override
171 protected Collection<ActionLink.ActionType> getBatches() {
172 return Collections.singletonList(ActionLink.ActionType.DELETE);
173 }
174
175 @Override
176 public ActionsPanel<Serializable> getActions(final IModel<Serializable> model) {
177 final ActionsPanel<Serializable> panel = super.getActions(model);
178
179 panel.add(new ActionLink<>() {
180
181 private static final long serialVersionUID = -7220222653598674870L;
182
183 @Override
184 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
185 ResourceTO resource = restClient.read(((ResourceTO) model.getObject()).getKey());
186 ConnInstanceTO connInstance = connectorRestClient.read(resource.getConnector());
187
188 IModel<ResourceTO> model = new CompoundPropertyModel<>(resource);
189 modal.setFormModel(model);
190
191 target.add(modal.setContent(new ResourceWizardBuilder(
192 resource, restClient, connectorRestClient, pageRef).
193 build(BaseModal.CONTENT_ID,
194 SyncopeConsoleSession.get().
195 owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())
196 ? AjaxWizard.Mode.EDIT
197 : AjaxWizard.Mode.READONLY)));
198
199 modal.header(new Model<>(MessageFormat.format(getString("resource.edit"), model.getObject().getKey())));
200 modal.show(true);
201 }
202 }, ActionLink.ActionType.EDIT, String.format("%s,%s", IdMEntitlement.RESOURCE_READ,
203 IdMEntitlement.RESOURCE_UPDATE));
204
205 panel.add(new ActionLink<>() {
206
207 private static final long serialVersionUID = -6467344504797047254L;
208
209 @Override
210 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
211 ResourceTO resource = restClient.read(((ResourceTO) model.getObject()).getKey());
212 ConnInstanceTO connInstance = connectorRestClient.read(resource.getConnector());
213
214 if (SyncopeConsoleSession.get().
215 owns(IdMEntitlement.RESOURCE_UPDATE, connInstance.getAdminRealm())) {
216
217 provisionModal.addSubmitButton();
218 } else {
219 provisionModal.removeSubmitButton();
220 }
221
222 IModel<ResourceTO> model = new CompoundPropertyModel<>(resource);
223 provisionModal.setFormModel(model);
224
225 target.add(provisionModal.setContent(
226 new ResourceProvisionPanel(provisionModal, resource, connInstance.getAdminRealm(), pageRef)));
227
228 provisionModal.header(new Model<>(MessageFormat.format(getString("resource.edit"),
229 model.getObject().getKey())));
230 provisionModal.show(true);
231 }
232 }, ActionLink.ActionType.MAPPING, String.format("%s,%s", IdMEntitlement.RESOURCE_READ,
233 IdMEntitlement.RESOURCE_UPDATE));
234
235 panel.add(new ActionLink<>() {
236
237 private static final long serialVersionUID = -1448897313753684142L;
238
239 @Override
240 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
241 ResourceTO resource = restClient.read(((ResourceTO) model.getObject()).getKey());
242
243 target.add(propTaskModal.setContent(new ConnObjects(resource, pageRef)));
244 propTaskModal.header(new StringResourceModel("resource.explore.list", Model.of(model.getObject())));
245 propTaskModal.show(true);
246 }
247 }, ActionLink.ActionType.EXPLORE_RESOURCE, IdMEntitlement.RESOURCE_LIST_CONNOBJECT);
248
249 panel.add(new ActionLink<>() {
250
251 private static final long serialVersionUID = 4800323783814856195L;
252
253 @Override
254 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
255 target.add(propTaskModal.setContent(
256 new PropagationTasks(propTaskModal, ((ResourceTO) model.getObject()).getKey(), pageRef)));
257 propTaskModal.header(new Model<>(MessageFormat.format(getString("task.propagation.list"),
258 ((ResourceTO) model.getObject()).getKey())));
259 propTaskModal.show(true);
260 }
261 }, ActionLink.ActionType.PROPAGATION_TASKS, IdRepoEntitlement.TASK_LIST);
262
263 panel.add(new ActionLink<>() {
264
265 private static final long serialVersionUID = -4699610013584898667L;
266
267 @Override
268 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
269 target.add(schedTaskModal.setContent(new PullTasks(
270 schedTaskModal, ((ResourceTO) model.getObject()).getKey(), pageRef)));
271 schedTaskModal.header(new Model<>(
272 MessageFormat.format(getString("task.pull.list"), ((ResourceTO) model.getObject()).getKey())));
273 schedTaskModal.show(true);
274 }
275 }, ActionLink.ActionType.PULL_TASKS, IdRepoEntitlement.TASK_LIST);
276
277 panel.add(new ActionLink<>() {
278
279 private static final long serialVersionUID = 2042227976628604686L;
280
281 @Override
282 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
283 target.add(schedTaskModal.setContent(new PushTasks(
284 schedTaskModal, ((ResourceTO) model.getObject()).getKey(), pageRef)));
285 schedTaskModal.header(new Model<>(
286 MessageFormat.format(getString("task.push.list"), ((ResourceTO) model.getObject()).getKey())));
287 schedTaskModal.show(true);
288 }
289 }, ActionLink.ActionType.PUSH_TASKS, IdRepoEntitlement.TASK_LIST);
290
291 panel.add(new ActionLink<>() {
292
293 private static final long serialVersionUID = -5962061673680621813L;
294
295 @Override
296 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
297 ResourceTO modelObject = restClient.read(((ResourceTO) model.getObject()).getKey());
298 target.add(propTaskModal.setContent(new ResourceStatusModal(pageRef, modelObject)));
299 propTaskModal.header(new Model<>(MessageFormat.format(getString("resource.reconciliation"),
300 ((ResourceTO) model.getObject()).getKey())));
301 propTaskModal.show(true);
302 }
303 }, ActionLink.ActionType.RECONCILIATION_RESOURCE, IdRepoEntitlement.USER_UPDATE);
304
305 panel.add(new ActionLink<>() {
306
307 private static final long serialVersionUID = -5432034353017728766L;
308
309 @Override
310 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
311 ResourceTO modelObject = restClient.read(((ResourceTO) model.getObject()).getKey());
312
313 target.add(historyModal.setContent(new AuditHistoryModal<>(
314 AuditElements.EventCategoryType.LOGIC,
315 "ResourceLogic",
316 modelObject,
317 IdMEntitlement.RESOURCE_UPDATE,
318 auditRestClient) {
319
320 private static final long serialVersionUID = -3712506022627033811L;
321
322 @Override
323 protected void restore(final String json, final AjaxRequestTarget target) {
324 try {
325 ResourceTO updated = MAPPER.readValue(json, ResourceTO.class);
326 restClient.update(updated);
327
328 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
329 } catch (Exception e) {
330 LOG.error("While restoring resource {}", ((ResourceTO) model.getObject()).getKey(), e);
331 SyncopeConsoleSession.get().onException(e);
332 }
333 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
334 }
335 }));
336
337 historyModal.header(
338 new Model<>(MessageFormat.format(getString("resource.menu.history"),
339 ((ResourceTO) model.getObject()).getKey())));
340
341 historyModal.show(true);
342 }
343 }, ActionLink.ActionType.VIEW_AUDIT_HISTORY, String.format("%s,%s", IdMEntitlement.RESOURCE_READ,
344 IdRepoEntitlement.AUDIT_LIST));
345
346 panel.add(new ActionLink<>() {
347
348 private static final long serialVersionUID = 7019899256702149874L;
349
350 @Override
351 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
352 try {
353 ResourceTO resource = restClient.read(((ResourceTO) model.getObject()).getKey());
354 resource.setKey("Copy of " + resource.getKey());
355
356 resource.getProvisions().forEach(provision -> {
357 if (provision.getMapping() != null) {
358 provision.getMapping().getLinkingItems().clear();
359 }
360 provision.getVirSchemas().clear();
361 });
362 target.add(modal.setContent(new ResourceWizardBuilder(
363 resource, restClient, connectorRestClient, pageRef).
364 build(BaseModal.CONTENT_ID, AjaxWizard.Mode.CREATE)));
365
366 modal.header(new Model<>(MessageFormat.format(getString("resource.clone"), resource.getKey())));
367 modal.show(true);
368 } catch (SyncopeClientException e) {
369 LOG.error("While cloning resource {}", ((ResourceTO) model.getObject()).getKey(), e);
370 SyncopeConsoleSession.get().onException(e);
371 }
372 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
373 }
374 }, ActionLink.ActionType.CLONE, IdMEntitlement.RESOURCE_CREATE);
375
376 panel.add(new ActionLink<>() {
377
378 private static final long serialVersionUID = 4516186028545701573L;
379
380 @Override
381 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
382 try {
383 restClient.delete(((ResourceTO) model.getObject()).getKey());
384 target.appendJavaScript(String.format("jsPlumb.remove('%s');",
385 ((ResourceTO) model.getObject()).getKey()));
386
387 SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
388 } catch (SyncopeClientException e) {
389 LOG.error("While deleting resource {}", ((ResourceTO) model.getObject()).getKey(), e);
390 SyncopeConsoleSession.get().onException(e);
391 }
392 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
393 }
394 }, ActionLink.ActionType.DELETE, IdMEntitlement.RESOURCE_DELETE, true);
395
396 return panel;
397 }
398
399 public static class ResourceSearchEvent implements Serializable {
400
401 private static final long serialVersionUID = 213974502541311941L;
402
403 protected final AjaxRequestTarget target;
404
405 protected final String keyword;
406
407 public ResourceSearchEvent(final AjaxRequestTarget target, final String keyword) {
408 this.target = target;
409 this.keyword = keyword;
410 }
411
412 public AjaxRequestTarget getTarget() {
413 return target;
414 }
415
416 public String getKeyword() {
417 return keyword;
418 }
419 }
420
421 public static class Builder extends DirectoryPanel.Builder<Serializable, Serializable, ResourceRestClient> {
422
423 private static final long serialVersionUID = -1391308721262593468L;
424
425 public Builder(final ResourceRestClient restClient, final PageReference pageRef) {
426 super(restClient, pageRef);
427 setShowResultPage(false);
428 }
429
430 @Override
431 protected WizardMgtPanel<Serializable> newInstance(final String id, final boolean wizardInModal) {
432 return new ResourceDirectoryPanel(id, this);
433 }
434 }
435 }