1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.fit.core;
20
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotEquals;
24 import static org.junit.jupiter.api.Assertions.assertNotNull;
25 import static org.junit.jupiter.api.Assertions.assertNull;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27
28 import com.fasterxml.jackson.databind.MappingIterator;
29 import com.fasterxml.jackson.dataformat.csv.CsvMapper;
30 import com.fasterxml.jackson.dataformat.csv.CsvSchema;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.Date;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.UUID;
37 import javax.ws.rs.core.HttpHeaders;
38 import javax.ws.rs.core.Response;
39 import org.apache.cxf.jaxrs.client.Client;
40 import org.apache.cxf.jaxrs.client.WebClient;
41 import org.apache.syncope.client.lib.SyncopeClient;
42 import org.apache.syncope.common.lib.Attr;
43 import org.apache.syncope.common.lib.SyncopeConstants;
44 import org.apache.syncope.common.lib.request.AnyObjectCR;
45 import org.apache.syncope.common.lib.to.AnyObjectTO;
46 import org.apache.syncope.common.lib.to.PagedResult;
47 import org.apache.syncope.common.lib.to.ProvisioningReport;
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.ReconStatus;
51 import org.apache.syncope.common.lib.to.UserTO;
52 import org.apache.syncope.common.lib.types.AnyTypeKind;
53 import org.apache.syncope.common.lib.types.MatchType;
54 import org.apache.syncope.common.lib.types.ResourceOperation;
55 import org.apache.syncope.common.lib.types.UnmatchingRule;
56 import org.apache.syncope.common.rest.api.RESTHeaders;
57 import org.apache.syncope.common.rest.api.beans.AnyQuery;
58 import org.apache.syncope.common.rest.api.beans.CSVPullSpec;
59 import org.apache.syncope.common.rest.api.beans.CSVPushSpec;
60 import org.apache.syncope.common.rest.api.beans.ReconQuery;
61 import org.apache.syncope.common.rest.api.service.ReconciliationService;
62 import org.apache.syncope.fit.AbstractITCase;
63 import org.identityconnectors.framework.common.objects.OperationalAttributes;
64 import org.identityconnectors.framework.common.objects.Uid;
65 import org.junit.jupiter.api.Test;
66 import org.springframework.jdbc.core.JdbcTemplate;
67
68 public class ReconciliationITCase extends AbstractITCase {
69
70 @Test
71 public void push() {
72
73 AnyObjectCR printerCR = AnyObjectITCase.getSample("reconciliation");
74 printerCR.getResources().clear();
75 AnyObjectTO printer = createAnyObject(printerCR).getEntity();
76 assertNotNull(printer.getKey());
77
78
79 JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
80 assertEquals(0, jdbcTemplate.queryForList(
81 "SELECT id FROM testPRINTER WHERE printername=?", printer.getName()).size());
82
83
84 ReconStatus status = RECONCILIATION_SERVICE.status(
85 new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).anyKey(printer.getName()).build());
86 assertNotNull(status);
87 assertEquals(AnyTypeKind.ANY_OBJECT, status.getAnyTypeKind());
88 assertEquals(printer.getKey(), status.getAnyKey());
89 assertEquals(MatchType.ANY, status.getMatchType());
90 assertNotNull(status.getOnSyncope());
91 assertNull(status.getOnResource());
92
93
94 PushTaskTO pushTask = new PushTaskTO();
95 pushTask.setPerformCreate(true);
96 pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
97 RECONCILIATION_SERVICE.push(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
98 anyKey(printer.getKey()).build(), pushTask);
99
100
101 assertEquals(1, jdbcTemplate.queryForList(
102 "SELECT id FROM testPRINTER WHERE printername=?", printer.getName()).size());
103
104
105 printer = ANY_OBJECT_SERVICE.read(printer.getKey());
106 assertTrue(printer.getResources().isEmpty());
107
108
109 status = RECONCILIATION_SERVICE.status(
110 new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).anyKey(printer.getName()).build());
111 assertNotNull(status);
112 assertNotNull(status.getOnSyncope());
113 assertNotNull(status.getOnResource());
114
115
116 Attr enable = status.getOnSyncope().getAttr(OperationalAttributes.ENABLE_NAME).orElse(null);
117 if (enable != null) {
118 status.getOnSyncope().getAttrs().remove(enable);
119 }
120
121 assertNull(status.getOnSyncope().getFiql());
122 assertNotNull(status.getOnResource().getFiql());
123 status.getOnResource().setFiql(null);
124 assertEquals(status.getOnSyncope(), status.getOnResource());
125 }
126
127 @Test
128 public void pull() {
129
130 AnyObjectCR printerCR = AnyObjectITCase.getSample("reconciliation");
131 printerCR.getResources().clear();
132 AnyObjectTO printer = createAnyObject(printerCR).getEntity();
133 assertNotNull(printer.getKey());
134 assertNotEquals("Nowhere", printer.getPlainAttr("location").get().getValues().get(0));
135
136
137 JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
138 jdbcTemplate.update(
139 "INSERT INTO TESTPRINTER (id, printername, location, deleted, lastmodification) VALUES (?,?,?,?,?)",
140 printer.getKey(), printer.getName(), "Nowhere", false, new Date());
141
142
143 ReconStatus status = RECONCILIATION_SERVICE.status(
144 new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).anyKey(printer.getName()).build());
145 assertNotNull(status);
146 assertNotNull(status.getOnSyncope());
147 assertNotNull(status.getOnResource());
148 assertNotEquals(status.getOnSyncope().getAttr("LOCATION"), status.getOnResource().getAttr("LOCATION"));
149
150
151 PullTaskTO pullTask = new PullTaskTO();
152 pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
153 pullTask.setPerformUpdate(true);
154 RECONCILIATION_SERVICE.pull(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
155 anyKey(printer.getName()).build(), pullTask);
156
157
158 printer = ANY_OBJECT_SERVICE.read(printer.getKey());
159 assertEquals("Nowhere", printer.getPlainAttr("location").get().getValues().get(0));
160 assertTrue(printer.getResources().isEmpty());
161 }
162
163 @Test
164 public void importSingle() {
165
166 String externalKey = UUID.randomUUID().toString();
167 String externalName = "printer" + getUUIDString();
168
169 JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
170 jdbcTemplate.update(
171 "INSERT INTO TESTPRINTER (id, printername, location, deleted, lastmodification) VALUES (?,?,?,?,?)",
172 externalKey, externalName, "Nowhere", false, new Date());
173
174
175 ReconStatus status = RECONCILIATION_SERVICE.status(
176 new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).fiql("ID==" + externalKey).build());
177 assertNotNull(status);
178 assertNull(status.getAnyTypeKind());
179 assertNull(status.getAnyKey());
180 assertNull(status.getMatchType());
181 assertNull(status.getOnSyncope());
182 assertNotNull(status.getOnResource());
183 assertEquals(externalKey, status.getOnResource().getAttr(Uid.NAME).get().getValues().get(0));
184 assertEquals(externalName, status.getOnResource().getAttr("PRINTERNAME").get().getValues().get(0));
185
186
187 PullTaskTO pullTask = new PullTaskTO();
188 pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
189 pullTask.setPerformCreate(true);
190 RECONCILIATION_SERVICE.pull(
191 new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).fiql("ID==" + externalKey).build(), pullTask);
192
193
194 AnyObjectTO printer = ANY_OBJECT_SERVICE.read(PRINTER, externalName);
195 assertNotNull(printer);
196 }
197
198 @Test
199 public void importCSV() {
200 ReconciliationService service = ADMIN_CLIENT.getService(ReconciliationService.class);
201 Client client = WebClient.client(service);
202 client.type(RESTHeaders.TEXT_CSV);
203
204 CSVPullSpec spec = new CSVPullSpec.Builder(AnyTypeKind.USER.name(), "username").build();
205 InputStream csv = getClass().getResourceAsStream("/test1.csv");
206
207 List<ProvisioningReport> results = service.pull(spec, csv);
208 assertEquals(AnyTypeKind.USER.name(), results.get(0).getAnyType());
209 assertNotNull(results.get(0).getKey());
210 assertEquals("donizetti", results.get(0).getName());
211 assertEquals("donizetti", results.get(0).getUidValue());
212 assertEquals(ResourceOperation.CREATE, results.get(0).getOperation());
213 assertEquals(ProvisioningReport.Status.SUCCESS, results.get(0).getStatus());
214
215 UserTO donizetti = USER_SERVICE.read(results.get(0).getKey());
216 assertNotNull(donizetti);
217 assertEquals("Gaetano", donizetti.getPlainAttr("firstname").get().getValues().get(0));
218 assertEquals(1, donizetti.getPlainAttr("loginDate").get().getValues().size());
219
220 UserTO cimarosa = USER_SERVICE.read(results.get(1).getKey());
221 assertNotNull(cimarosa);
222 assertEquals("Domenico Cimarosa", cimarosa.getPlainAttr("fullname").get().getValues().get(0));
223 assertEquals(2, cimarosa.getPlainAttr("loginDate").get().getValues().size());
224 }
225
226 @Test
227 public void exportCSV() throws IOException {
228 ReconciliationService service = ADMIN_CLIENT.getService(ReconciliationService.class);
229 Client client = WebClient.client(service);
230 client.accept(RESTHeaders.TEXT_CSV);
231
232 AnyQuery anyQuery = new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
233 fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("*ini").query()).
234 page(1).
235 size(1000).
236 orderBy("username ASC").
237 build();
238
239 CSVPushSpec spec = new CSVPushSpec.Builder(AnyTypeKind.USER.name()).ignorePaging(true).
240 field("username").
241 field("status").
242 plainAttr("firstname").
243 plainAttr("surname").
244 plainAttr("email").
245 plainAttr("loginDate").
246 build();
247
248 Response response = service.push(anyQuery, spec);
249 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
250 assertEquals(
251 "attachment; filename=" + SyncopeConstants.MASTER_DOMAIN + ".csv",
252 response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION));
253
254 PagedResult<UserTO> users = USER_SERVICE.search(anyQuery);
255 assertNotNull(users);
256
257 MappingIterator<Map<String, String>> reader = new CsvMapper().readerFor(Map.class).
258 with(CsvSchema.emptySchema().withHeader()).readValues((InputStream) response.getEntity());
259
260 int rows = 0;
261 for (; reader.hasNext(); rows++) {
262 Map<String, String> row = reader.next();
263
264 assertEquals(users.getResult().get(rows).getUsername(), row.get("username"));
265 assertEquals(users.getResult().get(rows).getStatus(), row.get("status"));
266
267 switch (row.get("username")) {
268 case "rossini":
269 assertEquals(spec.getNullValue(), row.get("email"));
270 assertTrue(row.get("loginDate").contains(spec.getArrayElementSeparator()));
271 break;
272
273 case "verdi":
274 assertEquals("verdi@syncope.org", row.get("email"));
275 assertEquals(spec.getNullValue(), row.get("loginDate"));
276 break;
277
278 case "bellini":
279 assertEquals(spec.getNullValue(), row.get("email"));
280 assertFalse(row.get("loginDate").contains(spec.getArrayElementSeparator()));
281 break;
282
283 default:
284 break;
285 }
286 }
287 assertEquals(rows, users.getTotalCount());
288 }
289 }