1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.fit.buildtools.cxf;
20
21 import java.sql.Connection;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.ResultSetMetaData;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Optional;
31 import java.util.Set;
32 import javax.jws.WebService;
33 import javax.sql.DataSource;
34 import net.tirasa.connid.bundles.soap.exceptions.ProvisioningException;
35 import net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning;
36 import net.tirasa.connid.bundles.soap.to.WSAttribute;
37 import net.tirasa.connid.bundles.soap.to.WSAttributeValue;
38 import net.tirasa.connid.bundles.soap.to.WSChange;
39 import net.tirasa.connid.bundles.soap.to.WSUser;
40 import net.tirasa.connid.bundles.soap.utilities.Operand;
41 import org.identityconnectors.common.StringUtil;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.jdbc.datasource.DataSourceUtils;
45
46 @WebService(
47 endpointInterface = "net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning",
48 serviceName = "Provisioning")
49 public class ProvisioningImpl implements Provisioning {
50
51 private static final Logger LOG = LoggerFactory.getLogger(Provisioning.class);
52
53 private final DataSource dataSource;
54
55 public ProvisioningImpl(final DataSource dataSource) {
56 this.dataSource = dataSource;
57 }
58
59 @Override
60 public String delete(final String accountid) throws ProvisioningException {
61 LOG.debug("Delete request received");
62
63 Connection conn = null;
64 try {
65 conn = DataSourceUtils.getConnection(dataSource);
66
67 try (PreparedStatement statement = conn.prepareStatement("DELETE FROM testuser WHERE userId=?")) {
68 statement.setString(1, accountid);
69
70 String query = "DELETE FROM testuser WHERE userId='" + accountid + "';";
71 LOG.debug("Execute query: " + query);
72
73 statement.executeUpdate();
74 }
75
76 return accountid;
77 } catch (SQLException e) {
78 throw new ProvisioningException("Delete operation failed", e);
79 } finally {
80 DataSourceUtils.releaseConnection(conn, dataSource);
81 }
82 }
83
84 @Override
85 public Boolean isSyncSupported() {
86 LOG.debug("isSyncSupported request received");
87
88 return Boolean.FALSE;
89 }
90
91 @Override
92 public String checkAlive() {
93 return "OK";
94 }
95
96 @Override
97 public String update(final String accountid, final List<WSAttributeValue> data)
98 throws ProvisioningException {
99
100 LOG.debug("Update request received");
101
102 if (data == null || data.isEmpty()) {
103 LOG.warn("Empty data recevied");
104 return accountid;
105 }
106
107 List<WSAttribute> schema = schema();
108 Set<String> schemaNames = new HashSet<>();
109 schema.forEach(attr -> schemaNames.add(attr.getName()));
110 schemaNames.add("__NAME__");
111 schemaNames.add("__PASSWORD__");
112
113 Connection conn = null;
114
115 try {
116 conn = DataSourceUtils.getConnection(dataSource);
117
118 String value;
119
120 StringBuilder set = new StringBuilder();
121 for (WSAttributeValue attr : data) {
122 if (schemaNames.contains(attr.getName())) {
123 if (attr.getValues() == null || attr.getValues().isEmpty()) {
124 value = null;
125 } else if (attr.getValues().size() == 1) {
126 value = attr.getValues().get(0).toString();
127 } else {
128 value = attr.getValues().toString();
129 }
130
131 if (!attr.isKey() || !accountid.equals(value)) {
132 if (set.length() > 0) {
133 set.append(',');
134 }
135
136 if (null == attr.getName()) {
137 set.append(attr.getName()).append('=');
138 } else {
139 switch (attr.getName()) {
140 case "__NAME__":
141 set.append("userId=");
142 break;
143 case "__PASSWORD__":
144 set.append("password=");
145 break;
146 default:
147 set.append(attr.getName()).append('=');
148 break;
149 }
150 }
151
152 set.append(Optional.ofNullable(value).map(s -> '\'' + s + '\'').orElse(null));
153 }
154 }
155 }
156
157 if (set.length() > 0) {
158 try (PreparedStatement statement =
159 conn.prepareStatement("UPDATE testuser SET " + set.toString() + " WHERE userId=?")) {
160 statement.setString(1, accountid);
161 String query = "UPDATE testuser SET " + set.toString() + " WHERE userId='" + accountid + "';";
162 LOG.debug("Execute query: " + query);
163
164 statement.executeUpdate();
165 }
166 }
167
168 return accountid;
169 } catch (SQLException e) {
170 LOG.error("Update failed", e);
171 throw new ProvisioningException("Update operation failed", e);
172 } finally {
173 DataSourceUtils.releaseConnection(conn, dataSource);
174 }
175 }
176
177 @Override
178 public List<WSUser> query(final Operand query) {
179 LOG.debug("Query request received");
180
181 List<WSUser> results = new ArrayList<>();
182
183 Connection conn = null;
184 try {
185
186 String queryString = "SELECT * FROM testuser" + (Optional.ofNullable(query)
187 .map(operand -> " WHERE " + operand.toString()).orElse(""));
188
189 queryString = queryString.replaceAll("__NAME__", "userId").
190 replaceAll("__UID__", "userId").
191 replaceAll("__PASSWORD__", "password");
192
193 LOG.debug("Execute query: {}", queryString);
194
195 if (queryString == null || queryString.length() == 0) {
196 throw new SQLException("Invalid query [" + queryString + ']');
197 }
198
199 conn = DataSourceUtils.getConnection(dataSource);
200 try (Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery(queryString)) {
201 ResultSetMetaData metaData = rs.getMetaData();
202 LOG.debug("Metadata: {}", metaData);
203
204 while (rs.next()) {
205 WSUser user = new WSUser();
206
207 for (int i = 0; i < metaData.getColumnCount(); i++) {
208 WSAttributeValue attr = new WSAttributeValue();
209 attr.setName(metaData.getColumnLabel(i + 1));
210 if (StringUtil.isNotBlank(rs.getString(i + 1))) {
211 attr.addValue(rs.getString(i + 1));
212 }
213 if ("userId".equalsIgnoreCase(metaData.getColumnName(i + 1))) {
214 attr.setKey(true);
215 user.setAccountid(rs.getString(i + 1));
216 }
217
218 user.addAttribute(attr);
219 }
220
221 results.add(user);
222 }
223
224 LOG.debug("Retrieved users: {}", results);
225 }
226 } catch (SQLException e) {
227 LOG.error("Search operation failed", e);
228 } finally {
229 DataSourceUtils.releaseConnection(conn, dataSource);
230 }
231
232 return results;
233 }
234
235 @Override
236 public String create(final List<WSAttributeValue> data) throws ProvisioningException {
237 LOG.debug("Create request received with data {}", data);
238
239 final List<WSAttribute> schema = schema();
240 final Set<String> schemaNames = new HashSet<>();
241 schema.forEach(attr -> schemaNames.add(attr.getName()));
242 schemaNames.add("__NAME__");
243 schemaNames.add("__PASSWORD__");
244
245 Connection conn = null;
246 String query = null;
247 try {
248 conn = DataSourceUtils.getConnection(dataSource);
249 String accountid;
250 try (Statement statement = conn.createStatement()) {
251 final StringBuilder keys = new StringBuilder();
252 final StringBuilder values = new StringBuilder();
253 accountid = null;
254 String value;
255 for (WSAttributeValue attr : data) {
256 if (schemaNames.contains(attr.getName())) {
257 LOG.debug("Bind attribute: {}", attr);
258
259 if (attr.getValues() == null || attr.getValues().isEmpty()) {
260 value = null;
261 } else if (attr.getValues().size() == 1) {
262 value = attr.getValues().get(0).toString();
263 } else {
264 value = attr.getValues().toString();
265 }
266
267 if (keys.length() > 0) {
268 keys.append(',');
269 }
270
271 if (null == attr.getName()) {
272 keys.append(attr.getName());
273 } else {
274 switch (attr.getName()) {
275 case "__NAME__":
276 keys.append("userId");
277 break;
278 case "__PASSWORD__":
279 keys.append("password");
280 break;
281 default:
282 keys.append(attr.getName());
283 break;
284 }
285 }
286
287 if (values.length() > 0) {
288 values.append(',');
289 }
290
291 values.append(Optional.ofNullable(value).map(s -> '\'' + s + '\'').orElse(null));
292
293 if (attr.isKey() && !attr.getValues().isEmpty()) {
294 accountid = attr.getValues().get(0).toString();
295 }
296 }
297 }
298 query = "INSERT INTO testuser (" + keys.toString() + ") VALUES (" + values.toString() + ')';
299 LOG.debug("Execute query: " + query);
300 statement.executeUpdate(query);
301 }
302
303 return accountid;
304 } catch (SQLException e) {
305 LOG.error("Creation failed:\n" + query, e);
306 throw new ProvisioningException("Create operation failed", e);
307 } finally {
308 DataSourceUtils.releaseConnection(conn, dataSource);
309 }
310 }
311
312 @Override
313 public int getLatestChangeNumber()
314 throws ProvisioningException {
315
316 LOG.debug("getLatestChangeNumber request received");
317
318 return 0;
319 }
320
321 @Override
322 public List<WSChange> sync()
323 throws ProvisioningException {
324
325 LOG.debug("sync request received");
326
327 return List.of();
328 }
329
330 @Override
331 public String resolve(final String username) throws ProvisioningException {
332
333 LOG.debug("Resolve request operation received: " + username);
334
335 String resolved = "";
336
337 Connection conn = null;
338 try {
339 conn = DataSourceUtils.getConnection(dataSource);
340 PreparedStatement statement =
341 conn.prepareStatement("SELECT userId FROM testuser WHERE userId=?");
342 statement.setString(1, username);
343
344 final String query = "SELECT userId FROM testuser WHERE userId='" + username + "';";
345
346 LOG.debug("Execute query: " + query);
347
348 ResultSet rs = statement.executeQuery();
349
350 resolved = rs.next() ? rs.getString(1) : null;
351
352 statement.close();
353
354 if (resolved == null) {
355 statement = conn.prepareStatement("SELECT roleName FROM role WHERE roleName=?");
356 statement.setString(1, username);
357 final String roleQuery = "SELECT roleName FROM role WHERE roleName='" + username + "';";
358 LOG.debug("Execute query: " + roleQuery);
359
360 rs = statement.executeQuery();
361
362 resolved = rs.next() ? rs.getString(1) : null;
363
364 statement.close();
365 }
366 } catch (SQLException e) {
367 throw new ProvisioningException("Resolve operation failed", e);
368 } finally {
369 DataSourceUtils.releaseConnection(conn, dataSource);
370 }
371
372 return resolved;
373 }
374
375 @Override
376 public List<WSAttribute> schema() {
377 LOG.debug("schema request received");
378
379 final List<WSAttribute> attrs = new ArrayList<>();
380
381 WSAttribute attr = new WSAttribute();
382 attr.setName("userId");
383 attr.setNullable(false);
384 attr.setPassword(false);
385 attr.setKey(true);
386 attr.setType("String");
387 attrs.add(attr);
388
389 attr = new WSAttribute();
390 attr.setName("password");
391 attr.setNullable(false);
392 attr.setPassword(true);
393 attr.setKey(false);
394 attr.setType("String");
395 attrs.add(attr);
396
397 attr = new WSAttribute();
398 attr.setName("type");
399 attr.setNullable(false);
400 attr.setPassword(false);
401 attr.setKey(false);
402 attr.setType("String");
403 attrs.add(attr);
404
405 attr = new WSAttribute();
406 attr.setName("residence");
407 attr.setNullable(true);
408 attr.setPassword(false);
409 attr.setKey(false);
410 attr.setType("String");
411 attrs.add(attr);
412
413 attr = new WSAttribute();
414 attr.setName("telephone");
415 attr.setNullable(true);
416 attr.setPassword(false);
417 attr.setKey(false);
418 attr.setType("String");
419 attrs.add(attr);
420
421 attr = new WSAttribute();
422 attr.setName("fax");
423 attr.setNullable(true);
424 attr.setPassword(false);
425 attr.setKey(false);
426 attr.setType("String");
427 attrs.add(attr);
428
429 attr = new WSAttribute();
430 attr.setName("preference");
431 attr.setNullable(true);
432 attr.setPassword(false);
433 attr.setKey(false);
434 attr.setType("String");
435 attrs.add(attr);
436
437 attr = new WSAttribute();
438 attr.setName("name");
439 attr.setNullable(true);
440 attr.setPassword(false);
441 attr.setKey(false);
442 attr.setType("String");
443 attrs.add(attr);
444
445 attr = new WSAttribute();
446 attr.setName("surname");
447 attr.setNullable(true);
448 attr.setPassword(false);
449 attr.setKey(false);
450 attr.setType("String");
451 attrs.add(attr);
452
453 attr = new WSAttribute();
454 attr.setName("fullname");
455 attr.setNullable(false);
456 attr.setPassword(false);
457 attr.setKey(false);
458 attr.setType("String");
459 attrs.add(attr);
460
461 attr = new WSAttribute();
462 attr.setName("birthdate");
463 attr.setNullable(true);
464 attr.setPassword(false);
465 attr.setKey(false);
466 attr.setType("Date");
467 attrs.add(attr);
468
469 attr = new WSAttribute();
470 attr.setName("telephone");
471 attr.setNullable(true);
472 attr.setPassword(false);
473 attr.setKey(false);
474 attr.setType("String");
475 attrs.add(attr);
476
477 attr = new WSAttribute();
478 attr.setName("gender");
479 attr.setNullable(true);
480 attr.setPassword(false);
481 attr.setKey(false);
482 attr.setType("String");
483 attrs.add(attr);
484
485 attr = new WSAttribute();
486 attr.setName("taxNumber");
487 attr.setNullable(true);
488 attr.setPassword(false);
489 attr.setKey(false);
490 attr.setType("String");
491 attrs.add(attr);
492
493 attr = new WSAttribute();
494 attr.setName("state");
495 attr.setNullable(true);
496 attr.setPassword(false);
497 attr.setKey(false);
498 attr.setType("String");
499 attrs.add(attr);
500
501 attr = new WSAttribute();
502 attr.setName("studyTitle");
503 attr.setNullable(true);
504 attr.setPassword(false);
505 attr.setKey(false);
506 attr.setType("String");
507 attrs.add(attr);
508
509 attr = new WSAttribute();
510 attr.setName("studyArea");
511 attr.setNullable(true);
512 attr.setPassword(false);
513 attr.setKey(false);
514 attr.setType("String");
515 attrs.add(attr);
516
517 attr = new WSAttribute();
518 attr.setName("job");
519 attr.setNullable(true);
520 attr.setPassword(false);
521 attr.setKey(false);
522 attr.setType("String");
523 attrs.add(attr);
524
525 attr = new WSAttribute();
526 attr.setName("companyType");
527 attr.setNullable(true);
528 attr.setPassword(false);
529 attr.setKey(false);
530 attr.setType("String");
531 attrs.add(attr);
532
533 attr = new WSAttribute();
534 attr.setName("companyName");
535 attr.setNullable(true);
536 attr.setPassword(false);
537 attr.setKey(false);
538 attr.setType("String");
539 attrs.add(attr);
540
541 attr = new WSAttribute();
542 attr.setName("vatNumber");
543 attr.setNullable(true);
544 attr.setPassword(false);
545 attr.setKey(false);
546 attr.setType("String");
547 attrs.add(attr);
548
549 attr = new WSAttribute();
550 attr.setName("mandatoryDisclaimer");
551 attr.setNullable(true);
552 attr.setPassword(false);
553 attr.setKey(false);
554 attr.setType("Boolean");
555 attrs.add(attr);
556
557 attr = new WSAttribute();
558 attr.setName("promoRCSDisclaimer");
559 attr.setNullable(true);
560 attr.setPassword(false);
561 attr.setKey(false);
562 attr.setType("Boolean");
563 attrs.add(attr);
564
565 attr = new WSAttribute();
566 attr.setName("promoThirdPartyDisclaimer");
567 attr.setNullable(true);
568 attr.setPassword(false);
569 attr.setKey(false);
570 attr.setType("Boolean");
571 attrs.add(attr);
572
573 return attrs;
574 }
575
576 @Override
577 public String authenticate(final String username, final String password)
578 throws ProvisioningException {
579
580 LOG.debug("authenticate request received");
581
582 return username;
583 }
584
585 @Override
586 public Boolean isAuthenticationSupported() {
587 LOG.debug("isAuthenticationSupported request received");
588
589 return Boolean.FALSE;
590 }
591 }