/*
* Copyright 2005-2007 WSO2, Inc. (http://wso2.com)
*
* 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.wso2.carbon.user.core.jdbc;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.sql.DataSource;
import org.apache.axiom.om.util.Base64;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.user.api.RealmConfiguration;
import org.wso2.carbon.user.core.Permission;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.claim.ClaimManager;
import org.wso2.carbon.user.core.claim.ClaimMapping;
import org.wso2.carbon.user.core.common.AbstractUserStoreManager;
import org.wso2.carbon.user.core.hybrid.HybridJDBCConstants;
import org.wso2.carbon.user.core.hybrid.HybridRoleManager;
import org.wso2.carbon.user.core.internal.UMListenerServiceComponent;
import org.wso2.carbon.user.core.listener.UserStoreManagerListener;
import org.wso2.carbon.user.core.profile.ProfileConfigurationManager;
import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.util.DatabaseUtil;
import org.wso2.carbon.user.core.util.JDBCRealmUtil;
import org.wso2.carbon.user.core.util.UserCoreUtil;
import org.wso2.carbon.utils.dbcreator.DatabaseCreator;
public class JDBCUserStoreManager extends AbstractUserStoreManager{
protected DataSource jdbcDataSource = null;
protected UserRealm jdbcUserRealm = null;
protected int tenantId;
protected Random random = new Random();
private static Log log = LogFactory.getLog(JDBCUserStoreManager.class);
public JDBCUserStoreManager(RealmConfiguration realmConfig, int tenantId) {
this.realmConfig = realmConfig;
this.tenantId = tenantId;
realmConfig.setUserStoreProperties(JDBCRealmUtil.getSQL(realmConfig
.getUserStoreProperties()));
}
/**
* This constructor is used by the support IS
*
* @param ds
* @param realmConfig
* @param tenantId
* @param addInitData
* @param tenantId
*/
public JDBCUserStoreManager(DataSource ds, RealmConfiguration realmConfig, int tenantId,
boolean addInitData) throws UserStoreException {
this(realmConfig, tenantId);
if (log.isDebugEnabled()) {
log.debug("Started " + System.currentTimeMillis());
}
realmConfig.setUserStoreProperties(JDBCRealmUtil.getSQL(realmConfig
.getUserStoreProperties()));
this.jdbcDataSource = ds;
hybridRoleManager = new HybridRoleManager(jdbcDataSource, tenantId, realmConfig, jdbcUserRealm);
if (addInitData) {
this.addInitialData();
}
if (log.isDebugEnabled()) {
log.debug("Ended " + System.currentTimeMillis());
}
}
public JDBCUserStoreManager(RealmConfiguration realmConfig, Map<String, Object> properties,
ClaimManager claimManager, ProfileConfigurationManager profileManager, UserRealm realm,
Integer tenantId) throws UserStoreException {
this(realmConfig, tenantId);
if (log.isDebugEnabled()) {
log.debug("Started " + System.currentTimeMillis());
}
this.claimManager = claimManager;
this.profileManager = profileManager;
this.jdbcUserRealm = realm;
jdbcDataSource = loadUserStoreSpacificDataSoruce();
if (jdbcDataSource == null) {
jdbcDataSource = (DataSource) properties.get(UserCoreConstants.DATA_SOURCE);
}
if (jdbcDataSource == null) {
jdbcDataSource = DatabaseUtil.getRealmDataSource(realmConfig);
properties.put(UserCoreConstants.DATA_SOURCE, jdbcDataSource);
}
if (jdbcDataSource == null) {
throw new UserStoreException("Data Source is null");
}
if (log.isDebugEnabled()) {
log.debug("The jdbcDataSource being used by JDBCUserStoreManager :: "
+ jdbcDataSource.hashCode());
}
realmConfig.setUserStoreProperties(JDBCRealmUtil.getSQL(realmConfig
.getUserStoreProperties()));
hybridRoleManager = new HybridRoleManager(jdbcDataSource, tenantId, realmConfig, jdbcUserRealm);
this.addInitialData();
if (log.isDebugEnabled()) {
log.debug("Ended " + System.currentTimeMillis());
}
}
public boolean isExistingUser(String userName) throws UserStoreException {
if (CarbonConstants.REGISTRY_SYSTEM_USERNAME.equals(userName)) {
return true;
}
return checkExistingUserName(userName);
}
public String[] listUsers(String filter, int maxItemLimit) throws UserStoreException {
String[] users = new String[0];
Connection dbConnection = null;
String sqlStmt = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
if (maxItemLimit == 0) {
return new String[0];
}
int givenMax = Integer.parseInt(realmConfig
.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_MAX_USER_LIST));
if (maxItemLimit < 0 || maxItemLimit > givenMax) {
maxItemLimit = givenMax;
}
try {
if (filter != null && filter.trim().length() != 0) {
filter = filter.trim();
filter = filter.replace("*", "%");
filter = filter.replace("?", "_");
} else {
filter = "%";
}
int i = 0;
List<String> lst = new LinkedList<String>();
dbConnection = getDBConnection();
if (dbConnection == null) {
throw new UserStoreException("null connection");
}
dbConnection.setAutoCommit(false);
dbConnection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_USER_FILTER);
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, filter);
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
prepStmt.setInt(2, tenantId);
}
rs = prepStmt.executeQuery();
while (rs.next()) {
if (i < maxItemLimit) {
String name = rs.getString(1);
if(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME.equals(name)){
continue;
}
lst.add(name);
} else {
break;
}
i++;
}
rs.close();
if (lst.size() > 0) {
users = (String[]) lst.toArray(new String[lst.size()]);
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
return users;
}
public String[] getRoleNames() throws UserStoreException {
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_ROLE_LIST);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving role name is null");
}
String[] names = getStringValuesFromDatabase(sqlStmt, tenantId);
if (isReadOnly() == true) {
String[] hybrids = hybridRoleManager.getHybridRoles();
names = UserCoreUtil.combineArrays(names, hybrids);
}
return names;
}
public String[] getRoleListOfUser(String userName) throws UserStoreException {
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_USER_ROLE);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving user roles is null");
}
String[] names;
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
names = getStringValuesFromDatabase(sqlStmt, userName, tenantId, tenantId, tenantId);
} else {
names = getStringValuesFromDatabase(sqlStmt, userName);
}
if (isReadOnly() == true) {
String[] hybrids = hybridRoleManager.getHybridRoleListOfUser(userName);
names = UserCoreUtil.combineArrays(names, hybrids);
}
return names;
}
public boolean isUserInRole(String username, String roleName) throws UserStoreException {
boolean hasRole = false;
return hasRole;
}
public String[] getUserListOfRole(String roleName) throws UserStoreException {
String[] names;
if (isReadOnly() == true && hybridRoleManager.isExistingRole(roleName)) {
names = hybridRoleManager.getUserListOfHybridRole(roleName);
} else {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_USERS_IN_ROLE);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving user roles is null");
}
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
names = getStringValuesFromDatabase(sqlStmt, roleName, tenantId, tenantId, tenantId);
} else {
names = getStringValuesFromDatabase(sqlStmt, roleName);
}
}
return names;
}
public boolean isExistingRole(String roleName) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_IS_ROLE_EXISTING);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for is role existing role null");
}
boolean isExisting = false;
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
isExisting = isValueExisting(sqlStmt, null, roleName, tenantId);
} else {
isExisting = isValueExisting(sqlStmt, null, roleName);
}
if (isExisting == false && isReadOnly() == true) {
isExisting = hybridRoleManager.isExistingRole(roleName);
}
return isExisting;
}
public String[] getAllProfileNames() throws UserStoreException {
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_PROFILE_NAMES);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving profile names is null");
}
String[] names;
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
names = getStringValuesFromDatabase(sqlStmt, tenantId);
} else {
names = getStringValuesFromDatabase(sqlStmt);
}
return names;
}
public String[] getProfileNames(String userName) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_PROFILE_NAMES_FOR_USER);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving is null");
}
String[] names;
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
names = getStringValuesFromDatabase(sqlStmt, userName, tenantId, tenantId);
} else {
names = getStringValuesFromDatabase(sqlStmt, userName);
}
if (names.length == 0) {
names = new String[] { UserCoreConstants.DEFAULT_PROFILE };
} else {
Arrays.sort(names);
if (Arrays.binarySearch(names, UserCoreConstants.DEFAULT_PROFILE) < 0) {
// we have to add the default profile
String[] newNames = new String[names.length + 1];
int i = 0;
for (i = 0; i < names.length; i++) {
newNames[i] = names[i];
}
newNames[i] = UserCoreConstants.DEFAULT_PROFILE;
names = newNames;
}
}
return names;
}
public int getUserId(String username) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_USERID_FROM_USERNAME);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving ID is null");
}
int id = -1;
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
id = DatabaseUtil.getIntegerValueFromDatabase(dbConnection, sqlStmt, username, tenantId);
} else {
id = DatabaseUtil.getIntegerValueFromDatabase(dbConnection, sqlStmt, username);
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
return id;
}
/**
*
* @param tenantId tenant id
* @return array of users of the tenant.
* @throws UserStoreException throws user store exception
*/
public String[] getUserNames(int tenantId) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_USERNAME_FROM_TENANT_ID);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving user names is null");
}
String[] userNames;
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
userNames = DatabaseUtil.getStringValuesFromDatabase(dbConnection, sqlStmt, tenantId);
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
return userNames;
}
/**
* @deprecated
*
* Returns the admin users for the given tenant.
* @return the admin user.
* @throws org.wso2.carbon.user.core.UserStoreException from the getUserNames()
*/
public String getAdminUser() throws UserStoreException {
String[] users = getUserListOfRole(this.realmConfig.getAdminRoleName());
if (users != null && users.length > 0) {
return users[0];
}
return null;
}
public int getTenantId() throws UserStoreException {
return this.tenantId;
}
public Map<String, String> getProperties(org.wso2.carbon.user.api.Tenant tenant)
throws org.wso2.carbon.user.api.UserStoreException {
return getProperties((Tenant) tenant);
}
public int getTenantId(String username) throws UserStoreException {
if (this.tenantId != 0) {
throw new UserStoreException("Not allowed to perform this operation");
}
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_TENANT_ID_FROM_USERNAME);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for retrieving ID is null");
}
int id = -1;
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
id = DatabaseUtil.getIntegerValueFromDatabase(dbConnection, sqlStmt, username);
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
return id;
}
// ******************** private methods ********************************
public Map<String, String> getUserPropertyValues(String userName, String[] propertyNames,
String profileName) throws UserStoreException {
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
Connection dbConnection = null;
String sqlStmt = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
String[] propertyNamesSorted = propertyNames.clone();
Arrays.sort(propertyNamesSorted);
Map<String, String> map = new HashMap<String, String>();
try {
dbConnection = getDBConnection();
sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_PROPS_FOR_PROFILE);
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, userName);
prepStmt.setString(2, profileName);
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
prepStmt.setInt(3, tenantId);
prepStmt.setInt(4, tenantId);
}
rs = prepStmt.executeQuery();
while (rs.next()) {
String name = rs.getString(1);
String value = rs.getString(2);
if (Arrays.binarySearch(propertyNamesSorted, name) < 0) {
continue;
}
map.put(name, value);
}
return map;
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
}
private String[] getStringValuesFromDatabase(String sqlStmt, Object... params)
throws UserStoreException {
String[] values = new String[0];
Connection dbConnection = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
dbConnection = getDBConnection();
values = DatabaseUtil.getStringValuesFromDatabase(dbConnection, sqlStmt, params);
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
return values;
}
protected Connection getDBConnection() throws SQLException {
Connection dbConnection = jdbcDataSource.getConnection();
dbConnection.setAutoCommit(false);
dbConnection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
return dbConnection;
}
private boolean isValueExisting(String sqlStmt, Connection dbConnection, Object... params) throws UserStoreException {
PreparedStatement prepStmt = null;
ResultSet rs = null;
boolean isExisting = false;
boolean doClose = false;
try {
if (dbConnection == null) {
dbConnection = getDBConnection();
doClose = true; //because we created it
}
if (DatabaseUtil.getIntegerValueFromDatabase(dbConnection, sqlStmt, params) > -1) {
isExisting = true;
}
return isExisting;
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
if (doClose) {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
}
}
protected boolean checkExistingUserName(String userName) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_IS_USER_EXISTING);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for is user existing null");
}
boolean isExisting = false;
String isUnique = realmConfig
.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_USERNAME_UNIQUE);
if ("true".equals(isUnique) && !CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME.equals(userName)) {
String uniquenesSql = realmConfig
.getUserStoreProperty(JDBCRealmConstants.USER_NAME_UNIQUE);
isExisting = isValueExisting(uniquenesSql, null, userName);
if(log.isDebugEnabled()) {
log.debug("The username should be unique across tenants.");
}
} else {
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
isExisting = isValueExisting(sqlStmt, null, userName, tenantId);
} else {
isExisting = isValueExisting(sqlStmt, null, userName);
}
}
return isExisting;
}
public boolean authenticate(String userName, Object credential) throws UserStoreException {
for (UserStoreManagerListener listener : UMListenerServiceComponent
.getUserStoreManagerListeners()) {
if (!listener.authenticate(userName, credential, this)) {
return true;
}
}
if (!checkUserNameValid(userName)) {
return false;
}
if (!checkUserPasswordValid(credential)) {
return false;
}
if (CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME.equals(userName)) {
log.error("Anonnymous user trying to login");
return false;
}
Connection dbConnection = null;
ResultSet rs = null;
PreparedStatement prepStmt = null;
String sqlstmt = null;
String password = (String) credential;
boolean isAuthed = false;
try {
dbConnection = getDBConnection();
dbConnection.setAutoCommit(false);
sqlstmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.SELECT_USER);
if (log.isDebugEnabled()) {
log.debug(sqlstmt);
}
prepStmt = dbConnection.prepareStatement(sqlstmt);
prepStmt.setString(1, userName);
if (sqlstmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
prepStmt.setInt(2, tenantId);
}
rs = prepStmt.executeQuery();
if (rs.next() == true) {
String storedPassword = rs.getString(3);
String saltValue = null;
if ("true".equals(realmConfig
.getUserStoreProperty(JDBCRealmConstants.STORE_SALTED_PASSWORDS))) {
saltValue = rs.getString(4);
}
boolean requireChange = rs.getBoolean(5);
Timestamp changedTime = rs.getTimestamp(6);
GregorianCalendar gc = new GregorianCalendar();
gc.add(GregorianCalendar.HOUR, -24);
Date date = gc.getTime();
if (requireChange == true && changedTime.before(date)) {
isAuthed = false;
} else {
password = this.preparePassword(password, saltValue);
if ((storedPassword != null) && (storedPassword.equals(password))) {
isAuthed = true;
}
}
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlstmt);
throw new UserStoreException("Authentication Failure");
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
if (log.isDebugEnabled()) {
log.debug("User " + userName + " login attempt. Login success :: " + isAuthed);
}
return isAuthed;
}
public boolean isReadOnly() throws UserStoreException {
if ("true".equals(realmConfig
.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_READ_ONLY))) {
return true;
}
return false;
}
public void addUser(String userName, Object credential, String[] roleList,
Map<String, String> claims, String profileName) throws UserStoreException {
this.addUser(userName, credential, roleList, claims, profileName, false);
}
public void addUser(String userName, Object credential, String[] roleList,
Map<String, String> claims, String profileName, boolean requirePasswordChange)
throws UserStoreException {
for (UserStoreManagerListener listener : UMListenerServiceComponent
.getUserStoreManagerListeners()) {
if (!listener.addUser(userName, credential, roleList, claims, profileName, this)) {
return;
}
}
// persist the user info. in the database.
persistUser(userName, credential, roleList, claims, profileName, requirePasswordChange);
}
/*
This method persists the user information in the database.
*/
private void persistUser(String userName, Object credential, String[] roleList,
Map<String, String> claims, String profileName,
boolean requirePasswordChange) throws UserStoreException {
if (!checkUserNameValid(userName)) {
throw new UserStoreException(
"User name not valid. User name must be a non null string with following format, " +
realmConfig.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_USER_NAME_JAVA_REG_EX));
}
if (!checkUserPasswordValid(credential)) {
throw new UserStoreException(
"Credential not valid. Credential must be a non null string with following format, " +
realmConfig.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_JAVA_REG_EX));
}
boolean isExisting = checkExistingUserName(userName);
if (isExisting) {
throw new UserStoreException("User name : " + userName
+ " exists in the system. Please pick another user name");
}
Connection dbConnection = null;
String password = (String) credential;
try {
dbConnection = getDBConnection();
String sqlStmt1 = realmConfig.getUserStoreProperty(JDBCRealmConstants.ADD_USER);
String saltValue = null;
if ("true".equals(realmConfig.getUserStoreProperties().get(
JDBCRealmConstants.STORE_SALTED_PASSWORDS))) {
byte[] bytes = new byte[16];
random.nextBytes(bytes);
saltValue = Base64.encode(bytes);
}
password = this.preparePassword(password, saltValue);
// do all 4 possibilities
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN) && (saltValue == null)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, userName, password, "",
requirePasswordChange, new Date(), tenantId);
} else if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN) && (saltValue != null)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, userName, password,
saltValue, requirePasswordChange, new Date(), tenantId);
} else if (!sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)
&& (saltValue == null)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, userName, password,
null, requirePasswordChange, new Date());
} else {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, userName, password,
requirePasswordChange, new Date());
}
String[] roles = null;
if (CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME.equals(userName)) {
roles = new String[0];
} else {
if (roleList == null || roleList.length == 0) {
roles = new String[] { this.realmConfig.getEveryOneRoleName() };
} else {
Arrays.sort(roleList);
if (Arrays.binarySearch(roleList, realmConfig.getEveryOneRoleName()) < 0) {
roles = new String[roleList.length + 1];
int i = 0;
for (i = 0; i < roleList.length; i++) {
roles[i] = roleList[i];
}
roles[i] = realmConfig.getEveryOneRoleName();
} else {
roles = roleList;
}
}
}
// add user to role.
String sqlStmt2 = null;
String type = DatabaseCreator.getDatabaseType(dbConnection);
sqlStmt2 = realmConfig.getUserStoreProperty(JDBCRealmConstants.ADD_ROLE_TO_USER
+ "-" + type);
if (sqlStmt2 == null) {
sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_ROLE_TO_USER);
}
if (sqlStmt2.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2, roles,
tenantId, userName, tenantId, tenantId);
} else {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2, roles,
tenantId, userName);
}
if (claims != null) {
// add the properties
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
Iterator<Map.Entry<String, String>> ite = claims.entrySet().iterator();
while (ite.hasNext()) {
Map.Entry<String, String> entry = ite.next();
String claimURI = entry.getKey();
String propName = claimManager.getAttributeName(claimURI);
String propValue = entry.getValue();
addProperty(dbConnection, userName, propName, propValue, profileName);
}
}
dbConnection.commit();
} catch (Throwable e) {
try {
dbConnection.rollback();
} catch (SQLException e1) {
log.error(e.getMessage(), e1);
throw new UserStoreException(e.getMessage(), e1);
}
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void addRole(String roleName, String[] userList, Permission[] permissions)
throws UserStoreException {
Connection dbConnection = null;
try {
if (!roleNameValid(roleName)) {
throw new UserStoreException(
"Role name not valid. Role name must be a non null string with following format, " +
realmConfig.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_ROLE_NAME_JAVA_REG_EX));
}
if (isExistingRole(roleName)) {
throw new UserStoreException(
"Role name: "+roleName+" in the system. Please pick another role name.");
}
dbConnection = getDBConnection();
if (isReadOnly() == true) {
hybridRoleManager.addHybridRole(roleName, userList);
} else {
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.ADD_ROLE);
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt, roleName, tenantId);
} else {
this.updateStringValuesToDatabase(dbConnection, sqlStmt, roleName);
}
if (userList != null) {
// add role to user
String type = DatabaseCreator.getDatabaseType(dbConnection);
String sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_USER_TO_ROLE +"-"+type);
if (sqlStmt2 == null) {
sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_USER_TO_ROLE);
}
if (sqlStmt2.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2,
userList, tenantId, roleName, tenantId, tenantId);
} else {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2,
userList, tenantId, roleName);
}
}
}
if (permissions != null) {
for (Permission permission : permissions) {
String resourceId = permission.getResourceId();
String action = permission.getAction();
jdbcUserRealm.getAuthorizationManager().authorizeRole(roleName, resourceId, action);
}
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void updateRoleName(String roleName, String newRoleName) throws UserStoreException {
if (isReadOnly() == true) {
hybridRoleManager.updateHybridRoleName(roleName, newRoleName);
} else {
if (realmConfig.getAdminRoleName().equals(roleName)) {
throw new UserStoreException("Cannot delete admin role");
}
if (realmConfig.getEveryOneRoleName().equals(roleName)) {
throw new UserStoreException("Cannot delete everyone role");
}
if (isExistingRole(newRoleName)) {
throw new UserStoreException(
"Role name: "+newRoleName+" in the system. Please pick another role name.");
}
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.UPDATE_ROLE_NAME);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for update role name is null");
}
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt, newRoleName, roleName,
tenantId);
} else {
this.updateStringValuesToDatabase(dbConnection, sqlStmt, newRoleName, roleName);
}
dbConnection.commit();
this.jdbcUserRealm.getAuthorizationManager().resetPermissionOnUpdateRole(roleName,
newRoleName);
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
}
/**
* JDBC User store supports bulk import.
* @return Always <code>true<code>.
*/
public boolean isBulkImportSupported() {
return true;
}
/**
* This method is to check whether multiple profiles are allowed with a particular user-store.
* For an example, currently, JDBC user store supports multiple profiles and where as ApacheDS
* does not allow.
* Currently, JDBC user store allows multiple profiles. Hence return true.
* @return boolean
*/
public boolean isMultipleProfilesAllowed() {
return true; //To change body of implemented methods use File | Settings | File Templates.
}
public void deleteRole(String roleName) throws UserStoreException {
if (isReadOnly() == true && hybridRoleManager.isExistingRole(roleName)) {
hybridRoleManager.deleteHybridRole(roleName);
} else {
if (realmConfig.getAdminRoleName().equals(roleName)) {
throw new UserStoreException("Cannot delete admin role");
}
if (realmConfig.getEveryOneRoleName().equals(roleName)) {
throw new UserStoreException("Cannot delete everyone role");
}
String sqlStmt1 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ON_DELETE_ROLE_REMOVE_USER_ROLE);
if (sqlStmt1 == null) {
throw new UserStoreException(
"The sql statement for delete user-role mapping is null");
}
String sqlStmt2 = realmConfig.getUserStoreProperty(JDBCRealmConstants.DELETE_ROLE);
if (sqlStmt2 == null) {
throw new UserStoreException("The sql statement for delete role is null");
}
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, roleName, tenantId,
tenantId);
this.updateStringValuesToDatabase(dbConnection, sqlStmt2, roleName, tenantId);
} else {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, roleName);
this.updateStringValuesToDatabase(dbConnection, sqlStmt2, roleName);
}
this.jdbcUserRealm.getAuthorizationManager().clearRoleAuthorization(roleName);
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt1);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
}
public void deleteUser(String userName) throws UserStoreException {
for (UserStoreManagerListener listener : UMListenerServiceComponent
.getUserStoreManagerListeners()) {
if (!listener.deleteUser(userName, this)) {
return;
}
}
if (realmConfig.getAdminUserName().equals(userName)) {
throw new UserStoreException("Cannot delete admin user");
}
String sqlStmt1 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ON_DELETE_USER_REMOVE_USER_ROLE);
if (sqlStmt1 == null) {
throw new UserStoreException("The sql statement for delete user-role mapping is null");
}
String sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ON_DELETE_USER_REMOVE_ATTRIBUTE);
if (sqlStmt2 == null) {
throw new UserStoreException("The sql statement for delete user attribute is null");
}
String sqlStmt3 = realmConfig.getUserStoreProperty(JDBCRealmConstants.DELETE_USER);
if (sqlStmt3 == null) {
throw new UserStoreException("The sql statement for delete user is null");
}
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, userName, tenantId,
tenantId);
this.updateStringValuesToDatabase(dbConnection, sqlStmt2, userName, tenantId,
tenantId);
this.updateStringValuesToDatabase(dbConnection, sqlStmt3, userName, tenantId);
} else {
this.updateStringValuesToDatabase(dbConnection, sqlStmt1, userName);
this.updateStringValuesToDatabase(dbConnection, sqlStmt2, userName);
this.updateStringValuesToDatabase(dbConnection, sqlStmt3, userName);
}
this.jdbcUserRealm.getAuthorizationManager().clearUserAuthorization(userName);
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt1 + " :: " + sqlStmt2);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void addRole(String roleName, String[] userList,
org.wso2.carbon.user.api.Permission[] permissions)
throws org.wso2.carbon.user.api.UserStoreException {
addRole(roleName, userList, (Permission[]) permissions);
}
public void updateUserListOfRole(String roleName, String deletedUsers[], String[] newUsers)
throws UserStoreException {
if (realmConfig.getEveryOneRoleName().equals(roleName)) {
throw new UserStoreException("Everyone role is not updatable");
}
if (deletedUsers != null) {
Arrays.sort(deletedUsers);
if (realmConfig.getAdminRoleName().equals(roleName)
&& Arrays.binarySearch(deletedUsers, realmConfig.getAdminUserName()) > -1) {
log.error("An attempt to remove Admin user from Admin role ");
throw new UserStoreException("Cannot remove Admin user from Admin role");
}
}
if (isReadOnly() == true && hybridRoleManager.isExistingRole(roleName)) {
hybridRoleManager.updateUserListOfHybridRole(roleName, deletedUsers, newUsers);
} else {
String sqlStmt1 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.REMOVE_USER_FROM_ROLE);
if (sqlStmt1 == null) {
throw new UserStoreException("The sql statement for remove user from role is null");
}
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
String type = DatabaseCreator.getDatabaseType(dbConnection);
String sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_USER_TO_ROLE + "-" + type);
if (sqlStmt2 == null) {
sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_USER_TO_ROLE);
}
if (sqlStmt2 == null) {
throw new UserStoreException("The sql statement for add user to role is null");
}
if (deletedUsers != null) {
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt1,
deletedUsers, tenantId, roleName, tenantId, tenantId);
} else {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt1,
deletedUsers, tenantId, roleName);
}
}
if (newUsers != null) {
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2,
newUsers, tenantId, roleName, tenantId, tenantId);
} else {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2,
newUsers, tenantId, roleName);
}
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
}
public void updateRoleListOfUser(String userName, String[] deletedRoles, String[] newRoles)
throws UserStoreException {
if (deletedRoles != null) {
Arrays.sort(deletedRoles);
if(Arrays.binarySearch(deletedRoles, realmConfig.getEveryOneRoleName()) > -1){
log.error("An attempt to remove "+userName+" user from Everyone role ");
throw new UserStoreException("Everyone role is not updatable");
}
}
if (deletedRoles != null) {
Arrays.sort(deletedRoles);
if (realmConfig.getAdminUserName().equals(userName)
&& Arrays.binarySearch(deletedRoles, realmConfig.getAdminRoleName()) > -1) {
log.error("An attempt to remove Admin user from Admin role ");
throw new UserStoreException("Cannot remove Admin user from Admin role");
}
}
if (isReadOnly() == true) {
hybridRoleManager.updateHybridRoleListOfUser(userName, deletedRoles, newRoles);
} else {
String sqlStmt1 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.REMOVE_ROLE_FROM_USER);
if (sqlStmt1 == null) {
throw new UserStoreException("The sql statement for remove user from role is null");
}
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
String type = DatabaseCreator.getDatabaseType(dbConnection);
String sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_ROLE_TO_USER + "-" + type);
if (sqlStmt2 == null) {
sqlStmt2 = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_ROLE_TO_USER);
}
if (sqlStmt2 == null) {
throw new UserStoreException("The sql statement for add user to role is null");
}
if (deletedRoles != null) {
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt1,
deletedRoles, tenantId, userName, tenantId, tenantId);
} else {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt1,
deletedRoles, tenantId, userName);
}
}
if (newRoles != null) {
if (sqlStmt1.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
// System.out.println("" +
// DatabaseUtil.getIntegerValueFromDatabase(dbConnection,
// sqlStmt, params));
// System.out.println("" +
// DatabaseUtil.getIntegerValueFromDatabase(dbConnection,
// sqlStmt, params));
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2,
newRoles, tenantId, userName, tenantId, tenantId);
} else {
DatabaseUtil.udpateUserRoleMappingInBatchMode(dbConnection, sqlStmt2,
newRoles, tenantId, userName);
}
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
}
public void setUserClaimValue(String userName, String claimURI, String claimValue,
String profileName) throws UserStoreException {
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
if (claimValue == null) {
throw new UserStoreException("Cannot set null values.");
}
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
ClaimMapping cMapping = (ClaimMapping) claimManager.getClaimMapping(claimURI);
String property;
if (cMapping != null) {
property = cMapping.getMappedAttribute();
} else {
property = claimURI;
}
String value = getProperty(dbConnection, userName, property, profileName);
if (value == null) {
addProperty(dbConnection, userName, property, claimValue, profileName);
} else {
updateProperty(dbConnection, userName, property, claimValue, profileName);
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (org.wso2.carbon.user.api.UserStoreException e) {
throw new UserStoreException(e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void setUserClaimValues(String userName, Map<String, String> claims, String profileName)
throws UserStoreException {
Connection dbConnection = null;
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
if (claims.get(UserCoreConstants.PROFILE_CONFIGURATION) == null) {
claims.put(UserCoreConstants.PROFILE_CONFIGURATION,
UserCoreConstants.DEFAULT_PROFILE_CONFIGURATION);
}
try {
dbConnection = getDBConnection();
Iterator<Map.Entry<String, String>> ite = claims.entrySet().iterator();
while (ite.hasNext()) {
Map.Entry<String, String> entry = ite.next();
String claimURI = entry.getKey();
ClaimMapping cMapping = (ClaimMapping) claimManager.getClaimMapping(claimURI);
String property = null;
if (cMapping != null) {
property = cMapping.getMappedAttribute();
} else {
property = claimURI;
}
String value = entry.getValue();
String existingValue = getProperty(dbConnection, userName, property, profileName);
if (existingValue == null) {
addProperty(dbConnection, userName, property, value, profileName);
} else {
updateProperty(dbConnection, userName, property, value, profileName);
}
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (org.wso2.carbon.user.api.UserStoreException e) {
throw new UserStoreException(e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void deleteUserClaimValue(String userName, String claimURI, String profileName)
throws UserStoreException {
Connection dbConnection = null;
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
try {
String property = null;
if (UserCoreConstants.PROFILE_CONFIGURATION.equals(claimURI)) {
property = UserCoreConstants.PROFILE_CONFIGURATION;
} else {
property = claimManager.getClaimMapping(claimURI).getMappedAttribute();
}
dbConnection = getDBConnection();
this.deleteProperty(dbConnection, userName, property, profileName);
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (org.wso2.carbon.user.api.UserStoreException e) {
throw new UserStoreException(e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void deleteUserClaimValues(String userName, String[] claims, String profileName)
throws UserStoreException {
Connection dbConnection = null;
if (profileName == null) {
profileName = UserCoreConstants.DEFAULT_PROFILE;
}
try {
dbConnection = getDBConnection();
for (String claimURI : claims) {
String property = claimManager.getClaimMapping(claimURI).getMappedAttribute();
this.deleteProperty(dbConnection, userName, property, profileName);
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (org.wso2.carbon.user.api.UserStoreException e) {
throw new UserStoreException(e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
public void updateCredential(String userName, Object newCredential, Object oldCredential)
throws UserStoreException {
for (UserStoreManagerListener listener : UMListenerServiceComponent
.getUserStoreManagerListeners()) {
if (!listener.updateCredential(userName, newCredential, oldCredential, this)) {
return;
}
}
if (this.authenticate(userName, oldCredential)) {
this.updateCredentialByAdmin(userName, newCredential);
} else {
log.error("Wrong username/password provided");
throw new UserStoreException("Wrong username/password provided");
}
}
public void updateCredentialByAdmin(String userName, Object newCredential)
throws UserStoreException {
for (UserStoreManagerListener listener : UMListenerServiceComponent
.getUserStoreManagerListeners()) {
if (!listener.updateCredentialByAdmin(userName, newCredential, this)) {
return;
}
}
if (!checkUserPasswordValid(newCredential)) {
throw new UserStoreException(
"Credential not valid. Credential must be a non null string with following format, " +
realmConfig.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_JAVA_REG_EX));
}
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.UPDATE_USER_PASSWORD);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for delete user claim value is null");
}
String saltValue = null;
if ("true".equals(realmConfig.getUserStoreProperties().get(
JDBCRealmConstants.STORE_SALTED_PASSWORDS))) {
byte[] bytes = new byte[16];
random.nextBytes(bytes);
saltValue = Base64.encode(bytes);
}
String password = this.preparePassword((String) newCredential, saltValue);
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN) && saltValue == null) {
updateStringValuesToDatabase(null, sqlStmt, password, false, new Date(), userName,
tenantId);
} else if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN) && saltValue != null) {
updateStringValuesToDatabase(null, sqlStmt, password, saltValue, false, new Date(),
userName, tenantId);
} else if (!sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN) && saltValue == null) {
updateStringValuesToDatabase(null, sqlStmt, password, false, new Date(), userName);
} else {
updateStringValuesToDatabase(null, sqlStmt, password, saltValue, false, new Date(),
userName);
}
}
public String[] getHybridRoles() throws UserStoreException {
String[] names = new String[0];
if (isReadOnly() == true) {
names = hybridRoleManager.getHybridRoles();
}
return names;
}
public Date getPasswordExpirationTime(String userName) throws UserStoreException {
Connection dbConnection = null;
ResultSet rs = null;
PreparedStatement prepStmt = null;
String sqlstmt = null;
Date date = null;
try {
dbConnection = getDBConnection();
dbConnection.setAutoCommit(false);
sqlstmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.SELECT_USER);
if (log.isDebugEnabled()) {
log.debug(sqlstmt);
}
prepStmt = dbConnection.prepareStatement(sqlstmt);
prepStmt.setString(1, userName);
if (sqlstmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
prepStmt.setInt(2, tenantId);
}
rs = prepStmt.executeQuery();
if (rs.next() == true) {
boolean requireChange = rs.getBoolean(5);
Timestamp changedTime = rs.getTimestamp(6);
if (requireChange) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(changedTime);
gc.add(GregorianCalendar.HOUR, 24);
date = gc.getTime();
}
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlstmt);
throw new UserStoreException(e.getMessage());
} finally {
DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
}
return date;
}
private void updateStringValuesToDatabase(Connection dbConnection, String sqlStmt,
Object... params) throws UserStoreException {
PreparedStatement prepStmt = null;
boolean localConnection = false;
try {
if (dbConnection == null) {
localConnection = true;
dbConnection = getDBConnection();
}
prepStmt = dbConnection.prepareStatement(sqlStmt);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
Object param = params[i];
if (param == null) {
throw new UserStoreException("Invalid data provided");
} else if (param instanceof String) {
prepStmt.setString(i + 1, (String) param);
} else if (param instanceof Integer) {
prepStmt.setInt(i + 1, (Integer) param);
} else if (param instanceof Date) {
//Timestamp timestamp = new Timestamp(((Date) param).getTime());
//prepStmt.setTimestamp(i + 1, timestamp);
prepStmt.setTimestamp(i + 1,new Timestamp(System.currentTimeMillis()));
} else if (param instanceof Boolean) {
prepStmt.setBoolean(i + 1, (Boolean) param);
}
}
}
int count = prepStmt.executeUpdate();
if(count == 0) {
log.info("No rows were updated");
}
if (log.isDebugEnabled()) {
log.debug("Executed querry is " + sqlStmt + " and number of updated rows :: "
+ count);
}
if (localConnection) {
dbConnection.commit();
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
if (localConnection) {
DatabaseUtil.closeAllConnections(dbConnection);
}
DatabaseUtil.closeAllConnections(null, prepStmt);
}
}
public void addProperty(Connection dbConnection, String userName, String propertyName,
String value, String profileName) throws UserStoreException {
try {
String type = DatabaseCreator.getDatabaseType(dbConnection);
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_USER_PROPERTY + "-" + type);
if (sqlStmt == null) {
sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.ADD_USER_PROPERTY);
}
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for add user property sql is null");
}
updateStringValuesToDatabase(dbConnection, sqlStmt, userName, tenantId, propertyName,
value, profileName, tenantId);
} catch (UserStoreException e) {
throw e;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
}
}
protected void updateProperty(Connection dbConnection, String userName, String propertyName,
String value, String profileName) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.UPDATE_USER_PROPERTY);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for add user property sql is null");
}
updateStringValuesToDatabase(dbConnection, sqlStmt, value, userName, tenantId,
propertyName, profileName, tenantId);
}
protected void deleteProperty(Connection dbConnection, String userName, String propertyName,
String profileName) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.DELETE_USER_PROPERTY);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for add user property sql is null");
}
updateStringValuesToDatabase(dbConnection, sqlStmt, userName, tenantId, propertyName,
profileName, tenantId);
}
protected String getProperty(Connection dbConnection, String userName, String propertyName,
String profileName) throws UserStoreException {
String sqlStmt = realmConfig
.getUserStoreProperty(JDBCRealmConstants.GET_PROP_FOR_PROFILE);
if (sqlStmt == null) {
throw new UserStoreException("The sql statement for add user property sql is null");
}
PreparedStatement prepStmt = null;
ResultSet rs = null;
String value = null;
try {
prepStmt = dbConnection.prepareStatement(sqlStmt);
prepStmt.setString(1, userName);
prepStmt.setString(2, propertyName);
prepStmt.setString(3, profileName);
if (sqlStmt.contains(UserCoreConstants.UM_TENANT_COLUMN)) {
prepStmt.setInt(4, tenantId);
prepStmt.setInt(5, tenantId);
}
rs = prepStmt.executeQuery();
while (rs.next()) {
value = rs.getString(1);
}
return value;
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + sqlStmt);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(null, rs, prepStmt);
}
}
protected String preparePassword(String password, String saltValue) throws UserStoreException {
try {
String digestInput = password;
if (saltValue != null) {
digestInput = password + saltValue;
}
String digsestFunction = realmConfig.getUserStoreProperties().get(
JDBCRealmConstants.DIGEST_FUNCTION);
if (digsestFunction != null) {
MessageDigest dgst = MessageDigest.getInstance(digsestFunction);
byte[] byteValue = dgst.digest(digestInput.getBytes());
password = Base64.encode(byteValue);
}
return password;
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
}
}
private void addInitialData() throws UserStoreException {
boolean isAdminRoleAdded = false;
if (!isExistingRole(realmConfig.getAdminRoleName())) {
this.addRole(realmConfig.getAdminRoleName(), null, null);
isAdminRoleAdded = true;
}
if (!isExistingRole(realmConfig.getEveryOneRoleName())) {
this.addRole(realmConfig.getEveryOneRoleName(), null, null);
}
String adminUserName = getAdminUser();
if (adminUserName != null) {
realmConfig.setAdminUserName(adminUserName);
} else {
if (!isExistingUser(realmConfig.getAdminUserName())) {
if ("true".equals(realmConfig
.getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_READ_ONLY))) {
log.error("Admin user name is not valid");
throw new UserStoreException("Admin user name is not valid");
}
// it is not required to notify to the listeners, just persist data.
this.persistUser(realmConfig.getAdminUserName(), realmConfig.getAdminPassword(),
null, null, null, false);
}
}
// use isUserInRole method
if (isAdminRoleAdded) {
this.updateRoleListOfUser(realmConfig.getAdminUserName(), null,
new String[] { realmConfig.getAdminRoleName() });
}
// anonymous user and role
if (!isExistingUser(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME) && !this.isReadOnly()) {
byte[] password = new byte[12];
random.nextBytes(password);
this.addUser(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, Base64.encode(password),
null, null, null);
}
// if the realm is read only the role will be hybrid
if (!isExistingRole(CarbonConstants.REGISTRY_ANONNYMOUS_ROLE_NAME)) {
this.addRole(CarbonConstants.REGISTRY_ANONNYMOUS_ROLE_NAME,
new String[] { CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME }, null);
}
}
private DataSource loadUserStoreSpacificDataSoruce() throws UserStoreException {
BasicDataSource ds = null;
String url = realmConfig.getUserStoreProperty(JDBCRealmConstants.DRIVER_NAME);
if (url != null) {
ds = new BasicDataSource();
ds.setDriverClassName(url);
ds.setUrl(realmConfig.getUserStoreProperty(JDBCRealmConstants.URL));
ds.setUsername(realmConfig.getUserStoreProperty(JDBCRealmConstants.USER_NAME));
ds.setPassword(realmConfig.getUserStoreProperty(JDBCRealmConstants.PASSWORD));
ds.setMaxActive(Integer.parseInt(realmConfig
.getUserStoreProperty(JDBCRealmConstants.MAX_ACTIVE)));
ds.setMinIdle(Integer.parseInt(realmConfig
.getUserStoreProperty(JDBCRealmConstants.MIN_IDLE)));
ds.setMaxWait(Integer.parseInt(realmConfig
.getUserStoreProperty(JDBCRealmConstants.MAX_WAIT)));
}
return ds;
}
public Map<String, String> getProperties(Tenant tenant) throws UserStoreException {
return this.realmConfig.getUserStoreProperties();
}
public void addRememberMe(String userName, String token)
throws org.wso2.carbon.user.api.UserStoreException {
Connection dbConnection = null;
try {
dbConnection = getDBConnection();
String[] values = DatabaseUtil.getStringValuesFromDatabase(dbConnection,
HybridJDBCConstants.GET_REMEMBERME_VALUE_SQL, userName, tenantId);
Date createdTime = Calendar.getInstance().getTime();
if (values != null && values.length > 0 && values[0].length() > 0) {
// udpate
DatabaseUtil.updateDatabase(dbConnection,
HybridJDBCConstants.UPDATE_REMEMBERME_VALUE_SQL, token, createdTime,
userName, tenantId);
} else {
// add
DatabaseUtil.updateDatabase(dbConnection,
HybridJDBCConstants.ADD_REMEMBERME_VALUE_SQL, userName, token, createdTime,
tenantId);
}
dbConnection.commit();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
/**
* Checks whether the token is existing or not.
*
* @param userName
* @param token
* @return
* @throws org.wso2.carbon.user.api.UserStoreException
*/
public boolean isExistingRememberMeToken(String userName, String token)
throws org.wso2.carbon.user.api.UserStoreException {
boolean isValid = false;
Connection dbConnection = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
String value = null;
Date createdTime = null;
try {
dbConnection = getDBConnection();
prepStmt = dbConnection.prepareStatement(HybridJDBCConstants.GET_REMEMBERME_VALUE_SQL);
prepStmt.setString(1, userName);
prepStmt.setInt(2, tenantId);
rs = prepStmt.executeQuery();
while (rs.next()) {
value = rs.getString(1);
createdTime = rs.getTimestamp(2);
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
log.error("Using sql : " + HybridJDBCConstants.GET_REMEMBERME_VALUE_SQL);
throw new UserStoreException(e.getMessage(), e);
} finally {
DatabaseUtil.closeAllConnections(null, rs, prepStmt);
}
if (value != null && createdTime != null) {
Calendar calendar = Calendar.getInstance();
Date nowDate = calendar.getTime();
calendar.setTime(createdTime);
calendar.add(Calendar.SECOND, CarbonConstants.REMEMBER_ME_COOKIE_TTL);
Date expDate = calendar.getTime();
if (expDate.before(nowDate)) {
// Do nothing remember me expired.
// Return the user gracefully
} else {
isValid = true;
}
}
return isValid;
}
public boolean isValidRememberMeToken(String userName, String token)
throws org.wso2.carbon.user.api.UserStoreException {
try {
if (isExistingUser(userName)) {
isExistingRememberMeToken(userName, token);
}
} catch (Exception e) {
log.error("Validating remember me token failed for" + userName);
// not throwing exception.
// because we need to seamlessly direct them to login uis
}
return false;
}
}