package org.gcube.datacatalogue.utillibrary.db; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The Class DBCaller. * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * * Feb 9, 2021 */ public class DBCaller { private static final Logger LOG = LoggerFactory.getLogger(DBCaller.class); private String ckanDBURL; private Integer ckanDBPort; private String ckanDBName; private String ckanDBUser; private String ckanDBPwd; /** * Instantiates a new DB caller. */ public DBCaller() { } /** * Instantiates a new DB caller. * * @param ckanDBURL the ckan DBURL * @param ckanDBPort the ckan DB port * @param ckanDBName the ckan DB name * @param ckanDBUser the ckan DB user * @param ckanDBPwd the ckan DB pwd */ public DBCaller(String ckanDBURL, Integer ckanDBPort, String ckanDBName, String ckanDBUser, String ckanDBPwd) { this.ckanDBURL = ckanDBURL; this.ckanDBPort = ckanDBPort; this.ckanDBName = ckanDBName; this.ckanDBUser = ckanDBUser; this.ckanDBPwd = ckanDBPwd; } /** * Retrieve connection from the pool. * * @return a connection available within the pool * @throws SQLException the SQL exception * @throws ClassNotFoundException the class not found exception */ private Connection getConnection() throws SQLException, ClassNotFoundException{ LOG.trace("CONNECTION REQUEST"); // create db connection Class.forName("org.postgresql.Driver"); String dbBaseConnectionURL = String.format("jdbc:postgresql://%s", ckanDBURL); if(ckanDBPort!=null) dbBaseConnectionURL+=":" + ckanDBPort; dbBaseConnectionURL+="/" + ckanDBName; LOG.debug("DB CONNECTION URL: "+dbBaseConnectionURL); LOG.debug("CKAN_DB_USER: "+ckanDBUser); Connection connection = DriverManager.getConnection(dbBaseConnectionURL, ckanDBUser, ckanDBPwd); LOG.trace("Returnig db connection"); return connection; } /** * Retrieve the map (groups id, capacity) with the groups to which the user belongs by querying directly the database. * * @param username the username * @return the groups by user from DB */ public Map getGroupsByUserFromDB(String username){ checkNotNull(username); LOG.debug("Get groups by user called for username: "+username); //couples (groups id, capacity) of the user in the group Map toReturn = new HashMap(); Connection connection = null; try{ String userId = getUserIdForUsername(username); connection = getConnection(); String joinQuery = "SELECT \"group_id\",\"capacity\" FROM \"public\".\"member\" " + "JOIN \"public\".\"group\" ON \"member\".\"group_id\" = \"group\".\"id\" where \"table_id\"=?" + " and \"table_name\"='user' and \"member\".\"state\"='active' and \"group\".\"state\"='active' and \"group\".\"is_organization\"=?;"; LOG.debug("Performing query: "+joinQuery); PreparedStatement preparedStatement = connection.prepareStatement(joinQuery); preparedStatement.setString(1, userId); preparedStatement.setBoolean(2, false); ResultSet rs = preparedStatement.executeQuery(); while (rs.next()) { toReturn.put(rs.getString("group_id"), RolesCkanGroupOrOrg.convertFromCapacity(rs.getString("capacity"))); } }catch(Exception e){ LOG.error("Failed to retrieve the groups to whom the user belongs. Error is " + e.getMessage()); return null; }finally{ closeConnection(connection); } LOG.debug("returning map: "+toReturn); return toReturn; } /** * Gets the user id for username. * * @param username the username * @return the user id for username */ private String getUserIdForUsername(String username) { LOG.debug("Get user id for username called for username: "+username); Connection connection = null; String userId = null; try{ connection = getConnection(); String selQuery = "SELECT \"id\" FROM \"public\".\"user\" WHERE \"name\"=?;"; LOG.debug("Performing query: "+selQuery); PreparedStatement preparedStatement = connection.prepareStatement(selQuery); preparedStatement.setString(1, username); ResultSet rs = preparedStatement.executeQuery(); while (rs.next()) { userId = rs.getString("id"); break; } LOG.debug("For username "+username+" returning the user id: "+userId); return userId; }catch(Exception e){ LOG.error("Failed to retrieve the user id for username:"+username+". Error is " + e.getMessage()); return null; }finally{ closeConnection(connection); } } /** * Retrieve the map (organisation id, capacity) with the organisations to which the user belongs by querying directly the database. * * @param username the username * @return the organizations by user from DB */ public Map getOrganizationsByUserFromDB(String username){ LOG.debug("Get organisations by user called"); checkNotNull(username); Map toReturn = new HashMap(); Connection connection = null; try{ String userId = getUserIdForUsername(username); connection = getConnection(); ResultSet rs; String joinQuery = "SELECT \"group_id\",\"capacity\" FROM \"public\".\"member\" " + "JOIN \"public\".\"group\" ON \"member\".\"group_id\" = \"group\".\"id\" where \"table_id\"=?" + " and \"table_name\"='user' and \"member\".\"state\"='active' and \"group\".\"state\"='active' and \"group\".\"is_organization\"=?;"; PreparedStatement preparedStatement = connection.prepareStatement(joinQuery); preparedStatement.setString(1, userId); preparedStatement.setBoolean(2, true); rs = preparedStatement.executeQuery(); while (rs.next()) { toReturn.put(rs.getString("group_id"), RolesCkanGroupOrOrg.convertFromCapacity(rs.getString("capacity"))); } }catch(Exception e){ LOG.error("Failed to retrieve the groups to whom the user belongs. Error is " + e.getMessage()); return null; }finally{ closeConnection(connection); } LOG.debug("returning map: "+toReturn); return toReturn; } /** * Gets the api key from username. * * @param username the username * @param state the state * @return the api key from username */ public String getApiKeyFromUsername(String username, String state) { LOG.debug("Request api key for user = " + username); // checks checkNotNull(username); checkArgument(!username.isEmpty()); // the connection Connection connection = null; String apiToReturn = null; try{ connection = getConnection(); String query = "SELECT \"apikey\" FROM \"user\" WHERE \"name\"=? and \"state\"=?;"; PreparedStatement preparedStatement = connection.prepareStatement(query); preparedStatement.setString(1, username); preparedStatement.setString(2, state); LOG.debug("The query is: "+preparedStatement.toString()); ResultSet rs = preparedStatement.executeQuery(); while (rs.next()) { apiToReturn = rs.getString("apikey"); LOG.debug("Api key "+apiToReturn.substring(0,10)+" MASKED-TOKEN retrieved for user " + username); break; } return apiToReturn; }catch(Exception e){ LOG.error("Unable to retrieve key for user " + username, e); }finally{ closeConnection(connection); } return null; } /** * Tries to close a connection. * * @param connection the connection */ private void closeConnection(Connection connection){ if(connection != null){ try{ connection.close(); LOG.trace("CONNECTION CLOSED"); }catch(Exception e){ LOG.error("Unable to close this connection ", e); } } } }