View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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 }