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.wizards.any;
20
21 import com.fasterxml.jackson.databind.json.JsonMapper;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Optional;
26 import javax.ws.rs.HttpMethod;
27 import javax.ws.rs.core.HttpHeaders;
28 import javax.ws.rs.core.MediaType;
29 import org.apache.syncope.client.console.SyncopeConsoleSession;
30 import org.apache.syncope.client.console.pages.BasePage;
31 import org.apache.syncope.client.console.panels.UserDirectoryPanel;
32 import org.apache.syncope.client.console.rest.ResourceRestClient;
33 import org.apache.syncope.client.console.rest.UserRestClient;
34 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
35 import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
36 import org.apache.syncope.client.lib.batch.BatchRequest;
37 import org.apache.syncope.client.ui.commons.Constants;
38 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
39 import org.apache.syncope.common.lib.request.LinkedAccountUR;
40 import org.apache.syncope.common.lib.request.UserUR;
41 import org.apache.syncope.common.lib.to.LinkedAccountTO;
42 import org.apache.syncope.common.lib.to.UserTO;
43 import org.apache.syncope.common.lib.types.PatchOperation;
44 import org.apache.syncope.common.rest.api.Preference;
45 import org.apache.syncope.common.rest.api.RESTHeaders;
46 import org.apache.syncope.common.rest.api.batch.BatchRequestItem;
47 import org.apache.wicket.PageReference;
48 import org.apache.wicket.ajax.AjaxRequestTarget;
49 import org.apache.wicket.event.IEvent;
50 import org.apache.wicket.event.IEventSink;
51 import org.apache.wicket.extensions.wizard.WizardModel;
52 import org.apache.wicket.model.IModel;
53
54 public class MergeLinkedAccountsWizardBuilder extends BaseAjaxWizardBuilder<UserTO> implements IEventSink {
55
56 private static final long serialVersionUID = -9142332740863374891L;
57
58 protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
59
60 protected final UserDirectoryPanel parentPanel;
61
62 protected final BaseModal<?> modal;
63
64 protected MergeLinkedAccountsWizardModel model;
65
66 protected final ResourceRestClient resourceRestClient;
67
68 protected final UserRestClient userRestClient;
69
70 public MergeLinkedAccountsWizardBuilder(
71 final IModel<UserTO> model,
72 final UserDirectoryPanel parentPanel,
73 final BaseModal<?> modal,
74 final ResourceRestClient resourceRestClient,
75 final UserRestClient userRestClient,
76 final PageReference pageRef) {
77
78 super(model.getObject(), pageRef);
79
80 this.parentPanel = parentPanel;
81 this.modal = modal;
82 this.resourceRestClient = resourceRestClient;
83 this.userRestClient = userRestClient;
84 }
85
86 @Override
87 protected WizardModel buildModelSteps(final UserTO modelObject, final WizardModel wizardModel) {
88 model = new MergeLinkedAccountsWizardModel(modelObject);
89 wizardModel.add(new MergeLinkedAccountsSearchPanel(model, getPageReference()));
90 wizardModel.add(new MergeLinkedAccountsResourcesPanel(model, getPageReference()));
91 wizardModel.add(new MergeLinkedAccountsReviewPanel(model, getPageReference()));
92 return wizardModel;
93 }
94
95 @Override
96 public void onEvent(final IEvent<?> event) {
97 if (event.getPayload() instanceof AjaxWizard.NewItemCancelEvent) {
98 ((AjaxWizard.NewItemCancelEvent<?>) event.getPayload()).getTarget().ifPresent(modal::close);
99 }
100 if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
101 Optional<AjaxRequestTarget> target =
102 ((AjaxWizard.NewItemFinishEvent<?>) event.getPayload()).getTarget();
103 try {
104 mergeAccounts();
105
106 parentPanel.info(parentPanel.getString(Constants.OPERATION_SUCCEEDED));
107 target.ifPresent(t -> {
108 ((BasePage) parentPanel.getPage()).getNotificationPanel().refresh(t);
109 parentPanel.updateResultTable(t);
110 modal.close(t);
111 });
112 } catch (Exception e) {
113 parentPanel.error(parentPanel.getString(Constants.ERROR) + ": " + e.getMessage());
114 target.ifPresent(t -> ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(t));
115 }
116 }
117 }
118
119 private void mergeAccounts() throws Exception {
120 UserTO mergingUserTO = model.getMergingUser();
121
122 UserUR userUR = new UserUR();
123 userUR.setKey(model.getBaseUser().getUsername());
124
125
126 mergingUserTO.getLinkedAccounts().forEach(acct -> {
127 LinkedAccountTO linkedAccount =
128 new LinkedAccountTO.Builder(acct.getResource(), acct.getConnObjectKeyValue()).
129 password(acct.getPassword()).
130 suspended(acct.isSuspended()).
131 username(acct.getUsername()).
132 build();
133 linkedAccount.getPlainAttrs().addAll(acct.getPlainAttrs());
134 linkedAccount.getPrivileges().addAll(acct.getPrivileges());
135 LinkedAccountUR patch = new LinkedAccountUR.Builder().
136 linkedAccountTO(linkedAccount).
137 operation(PatchOperation.ADD_REPLACE).
138 build();
139 userUR.getLinkedAccounts().add(patch);
140 });
141
142
143 mergingUserTO.getResources().forEach(resource -> {
144 String connObjectKeyValue = resourceRestClient.getConnObjectKeyValue(
145 resource, mergingUserTO.getType(), mergingUserTO.getKey());
146 LinkedAccountTO linkedAccount = new LinkedAccountTO.Builder(resource, connObjectKeyValue).build();
147 linkedAccount.getPlainAttrs().addAll(mergingUserTO.getPlainAttrs());
148 linkedAccount.getPrivileges().addAll(mergingUserTO.getPrivileges());
149 LinkedAccountUR patch = new LinkedAccountUR.Builder().
150 linkedAccountTO(linkedAccount).
151 operation(PatchOperation.ADD_REPLACE).
152 build();
153 userUR.getLinkedAccounts().add(patch);
154 });
155
156
157 String connObjectKeyValue = resourceRestClient.getConnObjectKeyValue(
158 model.getResource().getKey(),
159 mergingUserTO.getType(), mergingUserTO.getKey());
160 LinkedAccountTO linkedAccount = new LinkedAccountTO.Builder(model.getResource().getKey(), connObjectKeyValue).
161 password(mergingUserTO.getPassword()).
162 suspended(mergingUserTO.isSuspended()).
163 username(mergingUserTO.getUsername()).
164 build();
165 linkedAccount.getPlainAttrs().addAll(mergingUserTO.getPlainAttrs());
166 linkedAccount.getPrivileges().addAll(mergingUserTO.getPrivileges());
167 LinkedAccountUR patch = new LinkedAccountUR.Builder().linkedAccountTO(linkedAccount).
168 operation(PatchOperation.ADD_REPLACE).
169 build();
170 userUR.getLinkedAccounts().add(patch);
171
172 BatchRequest batchRequest = SyncopeConsoleSession.get().batch();
173
174
175 BatchRequestItem deleteRequest = new BatchRequestItem();
176 deleteRequest.setMethod(HttpMethod.DELETE);
177 deleteRequest.setRequestURI("/users/" + mergingUserTO.getKey());
178 deleteRequest.getHeaders().put(HttpHeaders.CONTENT_TYPE, List.of(MediaType.APPLICATION_JSON));
179 batchRequest.getItems().add(deleteRequest);
180
181
182 String updateUserPayload = MAPPER.writeValueAsString(userUR);
183 BatchRequestItem updateUser = new BatchRequestItem();
184 updateUser.setMethod(HttpMethod.PATCH);
185 updateUser.setRequestURI("/users/" + model.getBaseUser().getUsername());
186 updateUser.setHeaders(new HashMap<>());
187 updateUser.getHeaders().put(RESTHeaders.PREFER, List.of(Preference.RETURN_NO_CONTENT.toString()));
188 updateUser.getHeaders().put(HttpHeaders.ACCEPT, List.of(MediaType.APPLICATION_JSON));
189 updateUser.getHeaders().put(HttpHeaders.CONTENT_TYPE, List.of(MediaType.APPLICATION_JSON));
190 updateUser.getHeaders().put(HttpHeaders.CONTENT_LENGTH, List.of(updateUserPayload.length()));
191 updateUser.setContent(updateUserPayload);
192 batchRequest.getItems().add(updateUser);
193
194 Map<String, String> batchResponse = userRestClient.batch(batchRequest);
195 batchResponse.forEach((key, value) -> {
196 if (!value.equalsIgnoreCase("success")) {
197 throw new IllegalArgumentException("Unable to report a success operation status for " + key);
198 }
199 });
200 }
201 }