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.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 }