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.panels;
20  
21  import java.io.Serializable;
22  import java.util.List;
23  import java.util.stream.Collectors;
24  import org.apache.commons.lang3.SerializationUtils;
25  import org.apache.syncope.client.console.SyncopeConsoleSession;
26  import org.apache.syncope.client.console.SyncopeWebApplication;
27  import org.apache.syncope.client.console.audit.AuditHistoryModal;
28  import org.apache.syncope.client.console.commons.IdRepoConstants;
29  import org.apache.syncope.client.console.notifications.NotificationTasks;
30  import org.apache.syncope.client.console.pages.BasePage;
31  import org.apache.syncope.client.console.rest.AnyObjectRestClient;
32  import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
33  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
34  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
35  import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
36  import org.apache.syncope.client.console.wizards.WizardMgtPanel;
37  import org.apache.syncope.client.console.wizards.any.AnyObjectWrapper;
38  import org.apache.syncope.client.ui.commons.Constants;
39  import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
40  import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
41  import org.apache.syncope.common.lib.AnyOperations;
42  import org.apache.syncope.common.lib.SyncopeClientException;
43  import org.apache.syncope.common.lib.SyncopeConstants;
44  import org.apache.syncope.common.lib.request.AnyObjectUR;
45  import org.apache.syncope.common.lib.to.AnyObjectTO;
46  import org.apache.syncope.common.lib.to.AnyTypeClassTO;
47  import org.apache.syncope.common.lib.to.DerSchemaTO;
48  import org.apache.syncope.common.lib.to.PlainSchemaTO;
49  import org.apache.syncope.common.lib.to.ProvisioningResult;
50  import org.apache.syncope.common.lib.types.AnyEntitlement;
51  import org.apache.syncope.common.lib.types.AnyTypeKind;
52  import org.apache.syncope.common.lib.types.AuditElements;
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.event.Broadcast;
57  import org.apache.wicket.model.IModel;
58  import org.apache.wicket.model.Model;
59  import org.apache.wicket.model.ResourceModel;
60  import org.apache.wicket.model.StringResourceModel;
61  
62  public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyObjectRestClient> {
63  
64      private static final long serialVersionUID = -1100228004207271270L;
65  
66      protected AnyObjectDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
67          super(id, builder, wizardInModal);
68      }
69  
70      @Override
71      protected String paginatorRowsKey() {
72          return IdRepoConstants.PREF_ANYOBJECT_PAGINATOR_ROWS;
73      }
74  
75      @Override
76      protected String[] getDefaultAttributeSelection() {
77          return AnyObjectDisplayAttributesModalPanel.DEFAULT_SELECTION;
78      }
79  
80      @Override
81      public ActionsPanel<Serializable> getHeader(final String componentId) {
82          final ActionsPanel<Serializable> panel = super.getHeader(componentId);
83  
84          panel.add(new ActionLink<>() {
85  
86              private static final long serialVersionUID = -7978723352517770644L;
87  
88              @Override
89              public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
90                  target.add(displayAttributeModal.setContent(new AnyObjectDisplayAttributesModalPanel<>(
91                          displayAttributeModal,
92                          page.getPageReference(),
93                          plainSchemas.stream().map(PlainSchemaTO::getKey).collect(Collectors.toList()),
94                          derSchemas.stream().map(DerSchemaTO::getKey).collect(Collectors.toList()),
95                          type)));
96                  displayAttributeModal.addSubmitButton();
97                  displayAttributeModal.header(new ResourceModel("any.attr.display"));
98                  displayAttributeModal.show(true);
99              }
100 
101             @Override
102             protected boolean statusCondition(final Serializable modelObject) {
103                 return wizardInModal;
104             }
105         }, ActionType.CHANGE_VIEW, AnyEntitlement.READ.getFor(type)).hideLabel();
106         return panel;
107     }
108 
109     @Override
110     public ActionsPanel<AnyObjectTO> getActions(final IModel<AnyObjectTO> model) {
111         final ActionsPanel<AnyObjectTO> panel = super.getActions(model);
112 
113         panel.add(new ActionLink<>() {
114 
115             private static final long serialVersionUID = -7978723352517770644L;
116 
117             @Override
118             public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
119                 send(AnyObjectDirectoryPanel.this, Broadcast.EXACT,
120                         new AjaxWizard.EditItemActionEvent<>(
121                                 new AnyObjectWrapper(restClient.read(model.getObject().getKey())), target));
122             }
123         }, ActionType.EDIT,
124                 String.format("%s,%s", AnyEntitlement.READ.getFor(type), AnyEntitlement.UPDATE.getFor(type))).
125                 setRealms(realm, model.getObject().getDynRealms());
126 
127         if (wizardInModal) {
128             SyncopeWebApplication.get().getAnyDirectoryPanelAdditionalActionLinksProvider().get(
129                     type,
130                     model.getObject(),
131                     realm,
132                     altDefaultModal,
133                     getString("any.edit", new Model<>(new AnyObjectWrapper(model.getObject()))),
134                     this,
135                     pageRef).forEach(panel::add);
136 
137             panel.add(new ActionLink<>() {
138 
139                 private static final long serialVersionUID = -7978723352517770644L;
140 
141                 @Override
142                 public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
143                     target.add(utilityModal.setContent(new AnyPropagationTasks(
144                             utilityModal, AnyTypeKind.ANY_OBJECT, model.getObject().getKey(), pageRef)));
145 
146                     utilityModal.header(new StringResourceModel("any.propagation.tasks", model));
147                     utilityModal.show(true);
148                 }
149             }, ActionType.PROPAGATION_TASKS, IdRepoEntitlement.TASK_LIST);
150 
151             panel.add(new ActionLink<>() {
152 
153                 private static final long serialVersionUID = -7978723352517770644L;
154 
155                 @Override
156                 public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
157                     target.add(utilityModal.setContent(
158                             new NotificationTasks(AnyTypeKind.ANY_OBJECT, model.getObject().getKey(), pageRef)));
159                     utilityModal.header(new StringResourceModel("any.notification.tasks", model));
160                     utilityModal.show(true);
161                     target.add(utilityModal);
162                 }
163             }, ActionType.NOTIFICATION_TASKS, IdRepoEntitlement.TASK_LIST);
164         }
165         panel.add(new ActionLink<>() {
166 
167             private static final long serialVersionUID = -2878723352517770644L;
168 
169             @Override
170             public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
171                 model.setObject(restClient.read(model.getObject().getKey()));
172                 target.add(altDefaultModal.setContent(new AuditHistoryModal<>(
173                         AuditElements.EventCategoryType.LOGIC,
174                         "AnyObjectLogic",
175                         model.getObject(),
176                         AnyEntitlement.UPDATE.getFor(type),
177                         auditRestClient) {
178 
179                     private static final long serialVersionUID = -7440902560249531201L;
180 
181                     @Override
182                     protected void restore(final String json, final AjaxRequestTarget target) {
183                         AnyObjectTO original = model.getObject();
184                         try {
185                             AnyObjectTO updated = MAPPER.readValue(json, AnyObjectTO.class);
186                             AnyObjectUR updateReq = AnyOperations.diff(updated, original, false);
187                             ProvisioningResult<AnyObjectTO> result =
188                                     restClient.update(original.getETagValue(), updateReq);
189                             model.getObject().setLastChangeDate(result.getEntity().getLastChangeDate());
190 
191                             SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
192                             target.add(container);
193                         } catch (Exception e) {
194                             LOG.error("While restoring any object {}", model.getObject().getKey(), e);
195                             SyncopeConsoleSession.get().onException(e);
196                         }
197                         ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
198                     }
199                 }));
200 
201                 altDefaultModal.header(new StringResourceModel("auditHistory.title", model));
202 
203                 altDefaultModal.show(true);
204             }
205         }, ActionType.VIEW_AUDIT_HISTORY,
206                 String.format("%s,%s", AnyEntitlement.READ.getFor(type), IdRepoEntitlement.AUDIT_LIST)).
207                 setRealms(realm, model.getObject().getDynRealms());
208 
209         panel.add(new ActionLink<>() {
210 
211             private static final long serialVersionUID = -7978723352517770645L;
212 
213             @Override
214             public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
215                 final AnyObjectTO clone = SerializationUtils.clone(model.getObject());
216                 clone.setKey(null);
217                 send(AnyObjectDirectoryPanel.this, Broadcast.EXACT,
218                         new AjaxWizard.NewItemActionEvent<>(new AnyObjectWrapper(clone), target));
219             }
220 
221             @Override
222             protected boolean statusCondition(final AnyObjectTO modelObject) {
223                 return addAjaxLink.isVisibleInHierarchy() && realm.startsWith(SyncopeConstants.ROOT_REALM);
224             }
225         }, ActionType.CLONE, AnyEntitlement.CREATE.getFor(type)).setRealm(realm);
226 
227         panel.add(new ActionLink<>() {
228 
229             private static final long serialVersionUID = -7978723352517770646L;
230 
231             @Override
232             public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
233                 try {
234                     restClient.delete(model.getObject().getETagValue(), model.getObject().getKey());
235                     SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
236                     target.add(container);
237                 } catch (SyncopeClientException e) {
238                     LOG.error("While deleting any object {}", model.getObject().getKey(), e);
239                     SyncopeConsoleSession.get().onException(e);
240                 }
241                 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
242             }
243 
244             @Override
245             protected boolean statusCondition(final AnyObjectTO modelObject) {
246                 return realm.startsWith(SyncopeConstants.ROOT_REALM);
247             }
248         }, ActionType.DELETE, AnyEntitlement.DELETE.getFor(type), true).setRealm(realm);
249 
250         return panel;
251     }
252 
253     public static class Builder extends AnyDirectoryPanel.Builder<AnyObjectTO, AnyObjectRestClient> {
254 
255         private static final long serialVersionUID = -6828423611982275641L;
256 
257         public Builder(
258                 final List<AnyTypeClassTO> anyTypeClassTOs,
259                 final AnyObjectRestClient restClient,
260                 final String type,
261                 final PageReference pageRef) {
262 
263             super(anyTypeClassTOs, restClient, type, pageRef);
264             setShowResultPage(true);
265         }
266 
267         @Override
268         protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> newInstance(final String id, final boolean wizardInModal) {
269             return new AnyObjectDirectoryPanel(id, this, wizardInModal);
270         }
271     }
272 }