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.status;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.Optional;
25 import java.util.stream.Collectors;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.syncope.client.console.commons.DirectoryDataProvider;
28 import org.apache.syncope.client.console.commons.IdMConstants;
29 import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
30 import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
31 import org.apache.syncope.client.console.panels.DirectoryPanel;
32 import org.apache.syncope.client.console.panels.MultilevelPanel;
33 import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
34 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
35 import org.apache.syncope.client.console.rest.GroupRestClient;
36 import org.apache.syncope.client.console.rest.UserRestClient;
37 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
38 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
39 import org.apache.syncope.client.lib.SyncopeClient;
40 import org.apache.syncope.client.ui.commons.Constants;
41 import org.apache.syncope.client.ui.commons.panels.ModalPanel;
42 import org.apache.syncope.client.ui.commons.status.StatusBean;
43 import org.apache.syncope.client.ui.commons.status.StatusUtils;
44 import org.apache.syncope.common.lib.SyncopeConstants;
45 import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
46 import org.apache.syncope.common.lib.to.AnyTO;
47 import org.apache.syncope.common.lib.to.GroupTO;
48 import org.apache.syncope.common.lib.to.PullTaskTO;
49 import org.apache.syncope.common.lib.to.PushTaskTO;
50 import org.apache.syncope.common.lib.to.ResourceTO;
51 import org.apache.syncope.common.lib.types.AnyTypeKind;
52 import org.apache.syncope.common.lib.types.IdMEntitlement;
53 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
54 import org.apache.wicket.PageReference;
55 import org.apache.wicket.ajax.AjaxRequestTarget;
56 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
57 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
58 import org.apache.wicket.model.IModel;
59 import org.apache.wicket.model.StringResourceModel;
60 import org.apache.wicket.spring.injection.annot.SpringBean;
61
62 public class ResourceStatusDirectoryPanel
63 extends DirectoryPanel<StatusBean, StatusBean, DirectoryDataProvider<StatusBean>, AbstractAnyRestClient<?>>
64 implements ModalPanel {
65
66 private static final long serialVersionUID = -9148734710505211261L;
67
68 @SpringBean
69 protected UserRestClient userRestClient;
70
71 @SpringBean
72 protected GroupRestClient groupRestClient;
73
74 @SpringBean
75 protected AnyObjectRestClient anyObjectRestClient;
76
77 protected final MultilevelPanel multiLevelPanelRef;
78
79 protected String type;
80
81 protected final ResourceTO resource;
82
83 public ResourceStatusDirectoryPanel(
84 final MultilevelPanel multiLevelPanelRef,
85 final PageReference pageRef,
86 final String type,
87 final ResourceTO resource) {
88
89 super(MultilevelPanel.FIRST_LEVEL_ID, null, pageRef);
90 this.multiLevelPanelRef = multiLevelPanelRef;
91 this.type = type;
92 this.resource = resource;
93 this.itemKeyFieldName = "resource";
94
95 initResultTable();
96 }
97
98 @Override
99 protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<StatusBean, String> resultTableBuilder) {
100 resultTableBuilder.setMultiLevelPanel(multiLevelPanelRef);
101 }
102
103 @Override
104 protected List<IColumn<StatusBean, String>> getColumns() {
105 List<IColumn<StatusBean, String>> columns = new ArrayList<>();
106
107 columns.add(new PropertyColumn<>(new StringResourceModel(Constants.NAME_FIELD_NAME, this),
108 Constants.NAME_FIELD_NAME, Constants.NAME_FIELD_NAME));
109
110 return columns;
111 }
112
113 @Override
114 public ActionsPanel<StatusBean> getActions(final IModel<StatusBean> model) {
115 final ActionsPanel<StatusBean> panel = super.getActions(model);
116
117 panel.add(new ActionLink<>() {
118
119 private static final long serialVersionUID = -7978723352517770645L;
120
121 @Override
122 protected boolean statusCondition(final StatusBean bean) {
123 return StringUtils.isNotBlank(type);
124 }
125
126 @Override
127 public void onClick(final AjaxRequestTarget target, final StatusBean bean) {
128 multiLevelPanelRef.next(bean.getResource(),
129 new ReconStatusPanel(bean.getResource(), type, bean.getKey()),
130 target);
131 target.add(multiLevelPanelRef);
132 getTogglePanel().close(target);
133 }
134 }, ActionLink.ActionType.VIEW, IdMEntitlement.RESOURCE_GET_CONNOBJECT);
135
136 panel.add(new ActionLink<>() {
137
138 private static final long serialVersionUID = -7978723352517770645L;
139
140 @Override
141 protected boolean statusCondition(final StatusBean bean) {
142 return StringUtils.isNotBlank(type);
143 }
144
145 @Override
146 public void onClick(final AjaxRequestTarget target, final StatusBean bean) {
147 multiLevelPanelRef.next("PUSH " + bean.getResource(),
148 new ReconTaskPanel(
149 bean.getResource(),
150 new PushTaskTO(),
151 type,
152 bean.getKey(),
153 true,
154 multiLevelPanelRef,
155 pageRef),
156 target);
157 target.add(multiLevelPanelRef);
158 getTogglePanel().close(target);
159 }
160 }, ActionLink.ActionType.RECONCILIATION_PUSH, IdRepoEntitlement.TASK_EXECUTE);
161
162 panel.add(new ActionLink<>() {
163
164 private static final long serialVersionUID = -7978723352517770645L;
165
166 @Override
167 protected boolean statusCondition(final StatusBean bean) {
168 return StringUtils.isNotBlank(type);
169 }
170
171 @Override
172 public void onClick(final AjaxRequestTarget target, final StatusBean bean) {
173 multiLevelPanelRef.next("PULL " + bean.getResource(),
174 new ReconTaskPanel(
175 bean.getResource(),
176 new PullTaskTO(),
177 type,
178 bean.getKey(),
179 true,
180 multiLevelPanelRef,
181 pageRef),
182 target);
183 target.add(multiLevelPanelRef);
184 getTogglePanel().close(target);
185 }
186 }, ActionLink.ActionType.RECONCILIATION_PULL, IdRepoEntitlement.TASK_EXECUTE);
187
188 return panel;
189 }
190
191 public void updateResultTable(final String type, final AjaxRequestTarget target) {
192 this.type = type;
193
194 if (StringUtils.isNotBlank(type)) {
195 switch (type) {
196 case "USER":
197 restClient = userRestClient;
198 break;
199
200 case "GROUP":
201 restClient = groupRestClient;
202 break;
203
204 default:
205 restClient = anyObjectRestClient;
206 }
207 }
208
209 synchronized (this) {
210 dataProvider = dataProvider();
211 }
212
213 super.updateResultTable(target);
214 }
215
216 @Override
217 protected Collection<ActionLink.ActionType> getBatches() {
218 List<ActionLink.ActionType> batches = new ArrayList<>();
219 batches.add(ActionLink.ActionType.UNLINK);
220 batches.add(ActionLink.ActionType.LINK);
221 batches.add(ActionLink.ActionType.DEPROVISION);
222 batches.add(ActionLink.ActionType.PROVISION);
223 batches.add(ActionLink.ActionType.ASSIGN);
224 batches.add(ActionLink.ActionType.UNASSIGN);
225 return batches;
226 }
227
228 @Override
229 protected ResourceStatusDataProvider dataProvider() {
230 return new ResourceStatusDataProvider(rows);
231 }
232
233 @Override
234 protected String paginatorRowsKey() {
235 return IdMConstants.PREF_RECONCILIATION_PAGINATOR_ROWS;
236 }
237
238 protected class ResourceStatusDataProvider extends AbstractStatusBeanProvider {
239
240 private static final long serialVersionUID = 4586969457669796621L;
241
242 private final String fiql;
243
244 private final AbstractAnyRestClient<? extends AnyTO> restClient;
245
246 public ResourceStatusDataProvider(final int paginatorRows) {
247 super(paginatorRows, AnyTypeKind.USER.name().equals(type)
248 ? Constants.USERNAME_FIELD_NAME : Constants.NAME_FIELD_NAME);
249
250 if (StringUtils.isEmpty(type)) {
251 fiql = null;
252 restClient = null;
253 } else {
254 AbstractFiqlSearchConditionBuilder<?, ?, ?> bld;
255 switch (type) {
256 case "USER":
257 bld = SyncopeClient.getUserSearchConditionBuilder();
258 restClient = userRestClient;
259 break;
260
261 case "GROUP":
262 bld = SyncopeClient.getGroupSearchConditionBuilder();
263 restClient = groupRestClient;
264 break;
265
266 default:
267 bld = SyncopeClient.getAnyObjectSearchConditionBuilder(type);
268 restClient = anyObjectRestClient;
269 }
270 fiql = bld.isNotNull(Constants.KEY_FIELD_NAME).query();
271 }
272 }
273
274 @Override
275 protected List<StatusBean> getStatusBeans(final long first, final long count) {
276 List<StatusBean> statusBeans = new ArrayList<>();
277
278 if (fiql != null && restClient != null) {
279 int page = (int) first / paginatorRows;
280 List<? extends AnyTO> result = restClient.search(
281 SyncopeConstants.ROOT_REALM, fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort(), type);
282
283 statusBeans.addAll(result.stream().map(any -> StatusUtils.getStatusBean(any,
284 resource.getKey(),
285 null,
286 any instanceof GroupTO)).collect(Collectors.toList()));
287 }
288
289 return statusBeans;
290 }
291
292 @Override
293 public long size() {
294 return Optional.ofNullable(fiql).map(s -> restClient.count(SyncopeConstants.ROOT_REALM, s, type)).orElse(0);
295 }
296 }
297 }