/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.services.task.identity; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.naming.InitialContext; import javax.sql.DataSource; import org.kie.internal.task.api.UserGroupCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Data base server user group callback implementation that utilizes SQL queries * to get information about user, groups and relationship of these two. * <br/> * There are four configuration parameters required by this callback: * <ul> * <li>db.ds.jndi.name - JNDI name of the data source to be used for connections</li> * <li>db.user.query - query used to verify existence of the user (case sensitive, expects a single parameter on position 1)</li> * <li>db.roles.query - query user to check group existence (case sensitive, expects single parameter on position 1)</li> * <li>db.user.roles.query - query used to collect group for given user (case sensitive, expects single parameter on position 1, * retrieves group name from position 1 of returned result set)</li> * </ul> * */ public class DBUserGroupCallbackImpl extends AbstractUserGroupInfo implements UserGroupCallback { private static final Logger logger = LoggerFactory.getLogger(DBUserGroupCallbackImpl.class); protected static final String DEFAULT_PROPERTIES_NAME = "classpath:/jbpm.usergroup.callback.properties"; public static final String DS_JNDI_NAME = "db.ds.jndi.name"; public static final String PRINCIPAL_QUERY = "db.user.query"; public static final String USER_ROLES_QUERY = "db.user.roles.query"; public static final String ROLES_QUERY = "db.roles.query"; private Properties config; private DataSource ds; //no no-arg constructor to prevent cdi from auto deploy public DBUserGroupCallbackImpl(boolean activate) { String propertiesLocation = System.getProperty("jbpm.usergroup.callback.properties"); config = readProperties(propertiesLocation, DEFAULT_PROPERTIES_NAME); init(); } public DBUserGroupCallbackImpl(Properties config) { this.config = config; init(); } public boolean existsUser(String userId) { if (userId == null) { throw new IllegalArgumentException("UserId cannot be null"); } return checkExistence(this.config.getProperty(PRINCIPAL_QUERY), userId); } public boolean existsGroup(String groupId) { if (groupId == null) { throw new IllegalArgumentException("GroupId cannot be null"); } return checkExistence(this.config.getProperty(ROLES_QUERY), groupId); } public List<String> getGroupsForUser(String userId) { if (userId == null) { throw new IllegalArgumentException("UserId cannot be null"); } List<String> roles = new ArrayList<String>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = ds.getConnection(); ps = conn.prepareStatement(this.config.getProperty(USER_ROLES_QUERY)); try { ps.setString(1, userId); } catch (ArrayIndexOutOfBoundsException ignore) { } rs = ps.executeQuery(); while (rs.next()) { roles.add(rs.getString(1)); } } catch (Exception e) { logger.error("Error when checking roles in db, parameter: " + userId, e); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { } } if (ps != null) { try { ps.close(); } catch (SQLException e) { } } if (conn != null) { try { conn.close(); } catch (Exception ex) { } } } return roles; } protected Connection getConnection() throws SQLException { return ds.getConnection(); } private void init() { if (this.config == null || !this.config.containsKey(DS_JNDI_NAME) || !this.config.containsKey(PRINCIPAL_QUERY) || !this.config.containsKey(ROLES_QUERY) || !this.config.containsKey(USER_ROLES_QUERY)) { throw new IllegalArgumentException("All properties must be given ("+ DS_JNDI_NAME + "," + USER_ROLES_QUERY +"," + ROLES_QUERY +"," +USER_ROLES_QUERY +")"); } String jndiName = this.config.getProperty(DS_JNDI_NAME, "java:/DefaultDS"); try { InitialContext ctx = new InitialContext(); ds = (DataSource) ctx.lookup(jndiName); } catch (Exception e) { throw new IllegalStateException("Can get data source for DB usergroup callback, JNDI name: " + jndiName, e); } } protected boolean checkExistence(String querySql, String parameter) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; boolean result = false; try { conn = ds.getConnection(); ps = conn.prepareStatement(querySql); ps.setString(1, parameter); rs = ps.executeQuery(); if (rs.next()) { result = true; } } catch (Exception e) { logger.error("Error when checking user/group in db, parameter: " + parameter, e); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { } } if (ps != null) { try { ps.close(); } catch (SQLException e) { } } if (conn != null) { try { conn.close(); } catch (Exception ex) { } } } return result; } }