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 de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
23 import java.io.Serializable;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.stream.Collectors;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.commons.lang3.tuple.Pair;
30 import org.apache.syncope.client.console.SyncopeWebApplication;
31 import org.apache.syncope.client.console.commons.ITabComponent;
32 import org.apache.syncope.client.console.layout.AnyLayout;
33 import org.apache.syncope.client.console.layout.AnyLayoutUtils;
34 import org.apache.syncope.client.console.rest.RealmRestClient;
35 import org.apache.syncope.client.console.rest.RoleRestClient;
36 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
37 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
38 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
39 import org.apache.syncope.client.console.wizards.any.ConnObjectPanel;
40 import org.apache.syncope.client.ui.commons.ConnIdSpecialName;
41 import org.apache.syncope.client.ui.commons.Constants;
42 import org.apache.syncope.client.ui.commons.status.StatusUtils;
43 import org.apache.syncope.common.lib.SyncopeConstants;
44 import org.apache.syncope.common.lib.to.AnyTypeTO;
45 import org.apache.syncope.common.lib.to.ConnObject;
46 import org.apache.syncope.common.lib.to.PropagationStatus;
47 import org.apache.syncope.common.lib.to.ProvisioningResult;
48 import org.apache.syncope.common.lib.to.RealmTO;
49 import org.apache.syncope.common.lib.types.ExecStatus;
50 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
51 import org.apache.wicket.Component;
52 import org.apache.wicket.PageReference;
53 import org.apache.wicket.ajax.AjaxRequestTarget;
54 import org.apache.wicket.extensions.markup.html.tabs.ITab;
55 import org.apache.wicket.markup.html.WebMarkupContainer;
56 import org.apache.wicket.markup.html.basic.Label;
57 import org.apache.wicket.markup.html.panel.Panel;
58 import org.apache.wicket.model.IModel;
59 import org.apache.wicket.model.ResourceModel;
60 import org.apache.wicket.spring.injection.annot.SpringBean;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 public abstract class Realm extends WizardMgtPanel<RealmTO> {
65
66 private static final long serialVersionUID = -1100228004207271270L;
67
68 protected static final Logger LOG = LoggerFactory.getLogger(Realm.class);
69
70 @SpringBean
71 protected RoleRestClient roleRestClient;
72
73 @SpringBean
74 protected RealmRestClient realmRestClient;
75
76 protected final RealmTO realmTO;
77
78 protected final List<AnyTypeTO> anyTypes;
79
80 protected final int selectedIndex;
81
82 protected final RealmWizardBuilder wizardBuilder;
83
84 public Realm(
85 final String id,
86 final RealmTO realmTO,
87 final List<AnyTypeTO> anyTypes,
88 final int selectedIndex,
89 final PageReference pageRef) {
90
91 super(id, true);
92 this.realmTO = realmTO;
93 this.anyTypes = anyTypes;
94 this.selectedIndex = selectedIndex;
95
96 setPageRef(pageRef);
97
98 addInnerObject(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList(pageRef)).
99 setSelectedTab(selectedIndex));
100
101 this.wizardBuilder = buildNewItemPanelBuilder(pageRef);
102 addNewItemPanelBuilder(this.wizardBuilder, false);
103
104 setShowResultPanel(true);
105
106 modal.size(Modal.Size.Large);
107 setWindowClosedReloadCallback(modal);
108 }
109
110 protected RealmWizardBuilder buildNewItemPanelBuilder(final PageReference pageRef) {
111 return new RealmWizardBuilder(realmRestClient, pageRef);
112 }
113
114 public RealmTO getRealmTO() {
115 return realmTO;
116 }
117
118 protected List<ITab> buildTabList(final PageReference pageRef) {
119 List<ITab> tabs = new ArrayList<>();
120
121 tabs.add(new RealmDetailsTabPanel());
122
123 AnyLayout anyLayout = AnyLayoutUtils.fetch(
124 roleRestClient,
125 anyTypes.stream().map(AnyTypeTO::getKey).collect(Collectors.toList()));
126 for (AnyTypeTO anyType : anyTypes) {
127 tabs.add(new ITabComponent(
128 new ResourceModel("anyType." + anyType.getKey(), anyType.getKey()),
129 String.format("%s_SEARCH", anyType.getKey())) {
130
131 private static final long serialVersionUID = 1169585538404171118L;
132
133 @Override
134 public WebMarkupContainer getPanel(final String panelId) {
135 return new AnyPanel.Builder<>(
136 anyLayout.getAnyPanelClass(), panelId, anyType, realmTO, anyLayout, true, pageRef).build();
137 }
138
139 @Override
140 public boolean isVisible() {
141 return SyncopeWebApplication.get().getSecuritySettings().getAuthorizationStrategy().
142 isActionAuthorized(this, RENDER);
143 }
144 });
145 }
146
147 return tabs;
148 }
149
150 @Override
151 @SuppressWarnings("unchecked")
152 protected Panel customResultBody(final String panelId, final RealmTO item, final Serializable result) {
153 if (!(result instanceof ProvisioningResult)) {
154 throw new IllegalStateException("Unsupported result type");
155 }
156
157 MultilevelPanel mlp = new MultilevelPanel(panelId);
158 add(mlp);
159
160 PropagationStatus syncope = new PropagationStatus();
161 syncope.setStatus(ExecStatus.SUCCESS);
162 syncope.setResource(Constants.SYNCOPE);
163
164 List<PropagationStatus> propagations = new ArrayList<>();
165 propagations.add(syncope);
166 propagations.addAll(((ProvisioningResult) result).getPropagationStatuses());
167
168 ListViewPanel.Builder<PropagationStatus> builder =
169 new ListViewPanel.Builder<>(PropagationStatus.class, pageRef) {
170
171 private static final long serialVersionUID = -6809736686861678498L;
172
173 @Override
174 protected Component getValueComponent(final String key, final PropagationStatus bean) {
175 if ("afterObj".equalsIgnoreCase(key)) {
176 String remoteId = Optional.ofNullable(bean.getAfterObj()).
177 flatMap(afterObj -> afterObj.getAttr(ConnIdSpecialName.NAME).
178 filter(s -> !s.getValues().isEmpty()).map(s -> s.getValues().get(0))).
179 orElse(StringUtils.EMPTY);
180
181 return new Label("field", remoteId);
182 }
183
184 if ("status".equalsIgnoreCase(key)) {
185 return StatusUtils.getStatusImagePanel("field", bean.getStatus());
186 }
187
188 return super.getValueComponent(key, bean);
189 }
190 };
191
192 builder.setItems(propagations);
193
194 builder.includes("resource", "afterObj", "status");
195 builder.withChecks(ListViewPanel.CheckAvailability.NONE);
196 builder.setReuseItem(false);
197
198 ActionLink<PropagationStatus> connObjectLink = new ActionLink<>() {
199
200 private static final long serialVersionUID = -3722207913631435501L;
201
202 @Override
203 protected boolean statusCondition(final PropagationStatus bean) {
204 return !Constants.SYNCOPE.equals(bean.getResource())
205 && (ExecStatus.CREATED == bean.getStatus()
206 || ExecStatus.SUCCESS == bean.getStatus());
207 }
208
209 @Override
210 public void onClick(final AjaxRequestTarget target, final PropagationStatus status) {
211 mlp.next(status.getResource(), new RemoteRealmPanel(status), target);
212 }
213 };
214 SyncopeWebApplication.get().getStatusProvider().addConnObjectLink(builder, connObjectLink);
215
216 builder.addAction(new ActionLink<>() {
217
218 private static final long serialVersionUID = -3722207913631435501L;
219
220 @Override
221 protected boolean statusCondition(final PropagationStatus status) {
222 return StringUtils.isNotBlank(status.getFailureReason());
223 }
224
225 @Override
226 public void onClick(final AjaxRequestTarget target, final PropagationStatus status) {
227 mlp.next(status.getResource(), new PropagationErrorPanel(status.getFailureReason()), target);
228 }
229 }, ActionLink.ActionType.PROPAGATION_TASKS, StringUtils.EMPTY);
230
231 mlp.setFirstLevel(builder.build(MultilevelPanel.FIRST_LEVEL_ID));
232 return mlp;
233 }
234
235 protected abstract void onClickTemplate(AjaxRequestTarget target);
236
237 protected abstract void onClickCreate(AjaxRequestTarget target);
238
239 protected abstract void onClickEdit(AjaxRequestTarget target, RealmTO realmTO);
240
241 protected abstract void onClickDelete(AjaxRequestTarget target, RealmTO realmTO);
242
243 protected static class RemoteRealmPanel extends RemoteObjectPanel {
244
245 private static final long serialVersionUID = 4303365227411467563L;
246
247 protected final PropagationStatus bean;
248
249 protected RemoteRealmPanel(final PropagationStatus bean) {
250 this.bean = bean;
251 add(new ConnObjectPanel(
252 REMOTE_OBJECT_PANEL_ID,
253 Pair.<IModel<?>, IModel<?>>of(new ResourceModel("before"), new ResourceModel("after")),
254 getConnObjectTOs(),
255 false));
256 }
257
258 @Override
259 protected final Pair<ConnObject, ConnObject> getConnObjectTOs() {
260 return Pair.of(bean.getBeforeObj(), bean.getAfterObj());
261 }
262 }
263
264 protected class RealmDetailsTabPanel extends ITabComponent {
265
266 private static final long serialVersionUID = -5861786415855103549L;
267
268 protected RealmDetailsTabPanel() {
269 super(new ResourceModel("realm.details", "DETAILS"),
270 IdRepoEntitlement.REALM_CREATE, IdRepoEntitlement.REALM_UPDATE, IdRepoEntitlement.REALM_DELETE);
271 }
272
273 @Override
274 public Panel getPanel(final String panelId) {
275 ActionsPanel<RealmTO> actionPanel = new ActionsPanel<>("actions", null);
276
277 if (StringUtils.startsWith(realmTO.getFullPath(), SyncopeConstants.ROOT_REALM)) {
278 actionPanel.add(new ActionLink<>(realmTO) {
279
280 private static final long serialVersionUID = 2802988981431379827L;
281
282 @Override
283 public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
284 onClickCreate(target);
285 }
286 }, ActionLink.ActionType.CREATE, IdRepoEntitlement.REALM_CREATE).hideLabel();
287
288 actionPanel.add(new ActionLink<>(realmTO) {
289
290 private static final long serialVersionUID = 2802988981431379828L;
291
292 @Override
293 public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
294 onClickEdit(target, realmTO);
295 }
296 }, ActionLink.ActionType.EDIT, IdRepoEntitlement.REALM_UPDATE).hideLabel();
297
298 actionPanel.add(new ActionLink<>(realmTO) {
299
300 private static final long serialVersionUID = 2802988981431379827L;
301
302 @Override
303 public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
304 onClickTemplate(target);
305 }
306 }, ActionLink.ActionType.TEMPLATE, IdRepoEntitlement.REALM_UPDATE).hideLabel();
307
308 actionPanel.add(new ActionLink<>(realmTO) {
309
310 private static final long serialVersionUID = 2802988981431379829L;
311
312 @Override
313 public void onClick(final AjaxRequestTarget target, final RealmTO ignore) {
314 onClickDelete(target, realmTO);
315 }
316 }, ActionLink.ActionType.DELETE, IdRepoEntitlement.REALM_DELETE, true).hideLabel();
317 }
318
319 RealmDetails panel = new RealmDetails(panelId, realmTO, actionPanel, false);
320 panel.setContentEnabled(false);
321 actionPanel.setEnabled(true);
322 return panel;
323 }
324
325 @Override
326 public boolean isVisible() {
327 return SyncopeWebApplication.get().getSecuritySettings().getAuthorizationStrategy().
328 isActionAuthorized(this, RENDER);
329 }
330 }
331 }