From 631d55f52e643d07918174886295f61b6dc58ecd Mon Sep 17 00:00:00 2001 From: Thisara-Welmilla Date: Tue, 19 Nov 2024 09:44:10 +0530 Subject: [PATCH] Add dao layer support for the custom local auth extensions. --- .../common/cache/AuthenticatorCache.java | 47 +++ .../common/cache/AuthenticatorCacheEntry.java | 45 +++ .../common/cache/AuthenticatorCacheKey.java | 54 +++ .../AuthenticatorMgtSQLConstants.java | 86 +++++ .../dao/AuthenticatorManagementDAO.java | 93 +++++ .../impl/AuthenticatorManagementDAOImpl.java | 330 ++++++++++++++++++ .../impl/AuthenticatorManagementFacade.java | 101 ++++++ .../impl/CacheBackedAuthenticatorMgtDAO.java | 102 ++++++ 8 files changed, 858 insertions(+) create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCache.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheEntry.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheKey.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/constant/AuthenticatorMgtSQLConstants.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/AuthenticatorManagementDAO.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementDAOImpl.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementFacade.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/CacheBackedAuthenticatorMgtDAO.java diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCache.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCache.java new file mode 100644 index 000000000000..5a14def0dee6 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCache.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.cache; + +import org.wso2.carbon.identity.core.cache.BaseCache; +import org.wso2.carbon.utils.CarbonUtils; + +/** + * Cache for the Local Application Authenticator configurations. + */ +public class AuthenticatorCache extends BaseCache { + + private static final String CACHE_NAME = "AuthenticatorCache"; + private static final AuthenticatorCache INSTANCE = new AuthenticatorCache(); + + private AuthenticatorCache() { + + super(CACHE_NAME); + } + + /** + * Get Authenticator cache by the name instance. + * + * @return Authenticator cache by name instance. + */ + public static AuthenticatorCache getInstance() { + + CarbonUtils.checkSecurity(); + return INSTANCE; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheEntry.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheEntry.java new file mode 100644 index 000000000000..75c9fd158b8d --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheEntry.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.cache; + +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.core.cache.CacheEntry; + +/** + * Cache Entry for the User Defined Local Application Authenticator configurations. + */ +public class AuthenticatorCacheEntry extends CacheEntry { + + private UserDefinedLocalAuthenticatorConfig authenticatorConfig; + + public AuthenticatorCacheEntry(UserDefinedLocalAuthenticatorConfig authenticatorConfig) { + + this.authenticatorConfig = authenticatorConfig; + } + + public UserDefinedLocalAuthenticatorConfig getAuthenticatorConfig() { + + return authenticatorConfig; + } + + public void setAuthenticatorConfig(UserDefinedLocalAuthenticatorConfig authenticatorConfig) { + + this.authenticatorConfig = authenticatorConfig; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheKey.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheKey.java new file mode 100644 index 000000000000..51a25ddb5d9d --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/cache/AuthenticatorCacheKey.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.cache; + +import org.wso2.carbon.identity.core.cache.CacheKey; + +/** + * Cache key for the Local Application Authenticator configurations. + */ +public class AuthenticatorCacheKey extends CacheKey { + + private final String authenticatorName; + + public AuthenticatorCacheKey(String authenticatorName) { + + this.authenticatorName = authenticatorName; + } + + public String getAuthenticatorName() { + + return authenticatorName; + } + + @Override + public boolean equals(Object o) { + + if (!(o instanceof AuthenticatorCacheKey)) { + return false; + } + return authenticatorName.equals(((AuthenticatorCacheKey) o).getAuthenticatorName()); + } + + @Override + public int hashCode() { + + return authenticatorName.hashCode(); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/constant/AuthenticatorMgtSQLConstants.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/constant/AuthenticatorMgtSQLConstants.java new file mode 100644 index 000000000000..2eacbcec7fff --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/constant/AuthenticatorMgtSQLConstants.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.constant; + +/** + * SQL constants for authenticator configuration management service. + */ +public class AuthenticatorMgtSQLConstants { + + private AuthenticatorMgtSQLConstants() { + + } + + /** + * Column Names. + */ + public static class Column { + + public static final String IDP_ID = "ID"; + public static final String IDP_NAME = "IDP_NAME"; + public static final String TENANT_ID = "TENANT_ID"; + public static final String NAME = "NAME"; + public static final String IS_ENABLED = "IS_ENABLED"; + public static final String DEFINED_BY = "DEFINED_BY"; + public static final String AUTHENTICATION_TYPE = "AUTHENTICATION_TYPE"; + public static final String DISPLAY_NAME = "DISPLAY_NAME"; + public static final String ID = "ID"; + public static final String AUTHENTICATOR_ID = "AUTHENTICATOR_ID"; + public static final String PROPERTY_KEY = "PROPERTY_KEY"; + public static final String PROPERTY_VALUE = "PROPERTY_VALUE"; + public static final String IS_SECRET = "IS_SECRET"; + + private Column() { + + } + } + + /** + * Queries. + */ + public static class Query { + + public static final String ADD_AUTHENTICATOR_SQL = "INSERT INTO IDP_AUTHENTICATOR " + + "(TENANT_ID, IDP_ID, NAME, IS_ENABLED, DEFINED_BY, AUTHENTICATION_TYPE, DISPLAY_NAME) VALUES" + + " (:TENANT_ID;, (SELECT ID FROM IDP WHERE IDP.NAME = :IDP_NAME; AND IDP.TENANT_ID = :TENANT_ID;), " + + ":NAME;, :IS_ENABLED;, :DEFINED_BY;, :AUTHENTICATION_TYPE;, :DISPLAY_NAME;);"; + public static final String UPDATE_AUTHENTICATOR_SQL = "UPDATE IDP_AUTHENTICATOR SET IS_ENABLED = " + + ":IS_ENABLED;, DISPLAY_NAME = :DISPLAY_NAME; WHERE NAME = :NAME; AND TENANT_ID = :TENANT_ID;"; + public static final String GET_AUTHENTICATOR_SQL = "SELECT * FROM IDP_AUTHENTICATOR WHERE NAME = :NAME; " + + " AND TENANT_ID = :TENANT_ID;"; + public static final String GET_ALL_USER_DEFINED_AUTHENTICATOR_SQL = "SELECT * FROM IDP_AUTHENTICATOR " + + "WHERE DEFINED_BY = :DEFINED_BY; AND TENANT_ID = :TENANT_ID;"; + public static final String DELETE_AUTHENTICATOR_SQL = "DELETE FROM IDP_AUTHENTICATOR WHERE NAME = :NAME; " + + " AND TENANT_ID = :TENANT_ID;"; + public static final String GET_AUTHENTICATOR_ID_SQL = "SELECT ID FROM IDP_AUTHENTICATOR " + + "WHERE NAME = :NAME; AND TENANT_ID = :TENANT_ID;"; + public static final String ADD_AUTHENTICATOR_PROP_SQL = "INSERT INTO IDP_AUTHENTICATOR_PROPERTY " + + "(AUTHENTICATOR_ID, TENANT_ID, PROPERTY_KEY, PROPERTY_VALUE, IS_SECRET) VALUES " + + "(:AUTHENTICATOR_ID;, :TENANT_ID;, :PROPERTY_KEY;, :PROPERTY_VALUE;, :IS_SECRET;);"; + public static final String DELETE_AUTHENTICATOR_PROP_SQL = "DELETE FROM IDP_AUTHENTICATOR_PROPERTY " + + "WHERE AUTHENTICATOR_ID = :AUTHENTICATOR_ID; AND TENANT_ID = :TENANT_ID;"; + public static final String GET_AUTHENTICATOR_PROP_SQL = "SELECT PROPERTY_KEY, PROPERTY_VALUE, IS_SECRET" + + " FROM IDP_AUTHENTICATOR_PROPERTY " + + "WHERE AUTHENTICATOR_ID = :AUTHENTICATOR_ID; AND TENANT_ID = :TENANT_ID;"; + + private Query() { + + } + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/AuthenticatorManagementDAO.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/AuthenticatorManagementDAO.java new file mode 100644 index 000000000000..277dc6ce9011 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/AuthenticatorManagementDAO.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.dao; + +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.AuthenticationType; + +import java.util.List; + +/** + * This interface performs CRUD operations for the User defined Local Application Authenticator configurations. + */ +public interface AuthenticatorManagementDAO { + + /** + * Create a new user defined Local Application Authenticator configuration. + * + * @param authenticatorConfig Local Application Authenticator configuration. + * @param tenantId Tenant Id. + * + * @return Created UserDefinedLocalAuthenticatorConfig. + * @throws AuthenticatorMgtException If an error occurs while adding the authenticator configuration. + */ + UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId, AuthenticationType type) + throws AuthenticatorMgtException; + + /** + * Update a user defined Local Application Authenticator configuration. + * + * @param existingAuthenticatorConfig Existing Local Application Authenticator configuration. + * @param updatedAuthenticatorConfig New Local Application Authenticator configuration. + * @param tenantId Tenant Id. + * + * @return Updated UserDefinedLocalAuthenticatorConfig. + * @throws AuthenticatorMgtException If an error occurs while updating the authenticator configuration. + */ + UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig existingAuthenticatorConfig, + UserDefinedLocalAuthenticatorConfig updatedAuthenticatorConfig, int tenantId) + throws AuthenticatorMgtException; + + /** + * Retrieve a Local user defined Application Authenticator configuration by name. + * + * @param authenticatorConfigName Name of the Local Application Authenticator configuration. + * @param tenantId Tenant Id. + * + * @return Retrieved UserDefinedLocalAuthenticatorConfig + * @throws AuthenticatorMgtException If an error occurs while retrieving the authenticator configuration. + */ + UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator( + String authenticatorConfigName, int tenantId) throws AuthenticatorMgtException; + + /** + * Retrieve all user defined Local Application Authenticator configurations. + * + * @param tenantId Tenant Id. + * + * @return Retrieved UserDefinedLocalAuthenticatorConfig + * @throws AuthenticatorMgtException If an error occurs while retrieving the authenticator configurations. + */ + List getAllUserDefinedLocalAuthenticator(int tenantId) + throws AuthenticatorMgtException; + + /** + * Create a new Local Application Authenticator configuration. + * + * @param authenticatorConfigName Name of the Local Application Authenticator configuration. + * @param tenantId Tenant Id. + * + * @throws AuthenticatorMgtException If an error occurs while deleting the authenticator configuration. + */ + void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, UserDefinedLocalAuthenticatorConfig + authenticatorConfig, int tenantId) throws AuthenticatorMgtException; +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementDAOImpl.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementDAOImpl.java new file mode 100644 index 000000000000..09cd6fc25249 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementDAOImpl.java @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.database.utils.jdbc.NamedPreparedStatement; +import org.wso2.carbon.identity.application.common.constant.AuthenticatorMgtErrorConstants.ErrorMessages; +import org.wso2.carbon.identity.application.common.constant.AuthenticatorMgtSQLConstants.Column; +import org.wso2.carbon.identity.application.common.constant.AuthenticatorMgtSQLConstants.Query; +import org.wso2.carbon.identity.application.common.dao.AuthenticatorManagementDAO; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtServerException; +import org.wso2.carbon.identity.application.common.model.Property; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.AuthenticationType; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType; +import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * This class implements the AuthenticatorManagementDAO interface which perform CRUD operation on database. + */ +public class AuthenticatorManagementDAOImpl implements AuthenticatorManagementDAO { + + private static final Log LOG = LogFactory.getLog(AuthenticatorManagementDAOImpl.class); + public static final String IS_TRUE_VALUE = "1"; + public static final String IS_FALSE_VALUE = "0"; + public static final String LOCAL_IDP_NAME = "LOCAL"; + + public AuthenticatorManagementDAOImpl() { + } + + @Override + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, + int tenantId, AuthenticationType type) throws AuthenticatorMgtException { + + Connection dbConnection = IdentityDatabaseUtil.getDBConnection(true); + + try (NamedPreparedStatement statement = new NamedPreparedStatement(dbConnection, Query.ADD_AUTHENTICATOR_SQL)) { + statement.setString(Column.NAME, authenticatorConfig.getName()); + statement.setString(Column.DISPLAY_NAME, authenticatorConfig.getDisplayName()); + statement.setString(Column.DEFINED_BY, authenticatorConfig.getDefinedByType().toString()); + statement.setString(Column.AUTHENTICATION_TYPE, type.toString()); + statement.setInt(Column.IS_ENABLED, authenticatorConfig.isEnabled() ? 1 : 0); + statement.setString(Column.IDP_NAME, LOCAL_IDP_NAME); + statement.setInt(Column.TENANT_ID, tenantId); + statement.executeUpdate(); + + if (authenticatorConfig.getProperties() != null) { + + int authenticatorConfigID = getAuthenticatorIdentifier(dbConnection, authenticatorConfig.getName(), + tenantId); + addAuthenticatorProperties(dbConnection, authenticatorConfigID, authenticatorConfig.getProperties(), + tenantId); + } + IdentityDatabaseUtil.commitTransaction(dbConnection); + + return getUserDefinedLocalAuthenticatorByName(dbConnection, authenticatorConfig.getName(), tenantId); + } catch (SQLException | AuthenticatorMgtException e) { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Error while adding the authenticator: %s in tenant domain: %s. " + + "Rolling back added Authenticator information.", authenticatorConfig.getName(), + IdentityTenantUtil.getTenantDomain(tenantId))); + } + IdentityDatabaseUtil.rollbackTransaction(dbConnection); + + ErrorMessages error = ErrorMessages.ERROR_WHILE_ADDING_AUTHENTICATOR; + throw new AuthenticatorMgtServerException(error.getMessage(), error.getMessage(), error.getCode(), e); + } finally { + IdentityDatabaseUtil.closeConnection(dbConnection); + } + } + + @Override + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig existingAuthenticatorConfig, + UserDefinedLocalAuthenticatorConfig updatedAuthenticatorConfig, int tenantId) + throws AuthenticatorMgtException { + + Connection dbConnection = IdentityDatabaseUtil.getDBConnection(true); + try { + if (isBasicInfoUpdated(existingAuthenticatorConfig, updatedAuthenticatorConfig)) { + try (NamedPreparedStatement statement = new NamedPreparedStatement(dbConnection, + Query.UPDATE_AUTHENTICATOR_SQL)) { + statement.setString(Column.DISPLAY_NAME, updatedAuthenticatorConfig.getDisplayName()); + statement.setInt(Column.IS_ENABLED, updatedAuthenticatorConfig.isEnabled() ? 1 : 0); + statement.setString(Column.NAME, existingAuthenticatorConfig.getName()); + statement.setInt(Column.TENANT_ID, tenantId); + statement.executeUpdate(); + } + } + + // Will delete all the properties of given authenticator and add the updated properties. + int authenticatorConfigID = getAuthenticatorIdentifier(dbConnection, + existingAuthenticatorConfig.getName(), tenantId); + deletedAuthenticatorProperties(dbConnection, authenticatorConfigID, tenantId); + addAuthenticatorProperties(dbConnection, authenticatorConfigID, updatedAuthenticatorConfig.getProperties(), + tenantId); + + IdentityDatabaseUtil.commitTransaction(dbConnection); + + return getUserDefinedLocalAuthenticatorByName(dbConnection, updatedAuthenticatorConfig.getName(), tenantId); + } catch (SQLException e) { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Error while updating the authenticator: %s in tenant domain: %s. " + + "Rolling back updated Authenticator information.", + existingAuthenticatorConfig.getName(), IdentityTenantUtil.getTenantDomain(tenantId))); + } + IdentityDatabaseUtil.rollbackTransaction(dbConnection); + ErrorMessages error = ErrorMessages.ERROR_WHILE_UPDATING_AUTHENTICATOR; + throw new AuthenticatorMgtServerException(error.getMessage(), error.getMessage(), error.getCode(), e); + } finally { + IdentityDatabaseUtil.closeConnection(dbConnection); + } + } + + @Override + public UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator( + String authenticatorConfigName, int tenantId) throws AuthenticatorMgtException { + + Connection dbConnection = IdentityDatabaseUtil.getDBConnection(false); + try { + UserDefinedLocalAuthenticatorConfig config = getUserDefinedLocalAuthenticatorByName( + dbConnection, authenticatorConfigName, tenantId); + + return config; + } finally { + IdentityDatabaseUtil.closeConnection(dbConnection); + } + } + + @Override + public List getAllUserDefinedLocalAuthenticator(int tenantId) + throws AuthenticatorMgtException { + + try (Connection dbConnection = IdentityDatabaseUtil.getDBConnection(true); + NamedPreparedStatement statement = new NamedPreparedStatement(dbConnection, + Query.GET_ALL_USER_DEFINED_AUTHENTICATOR_SQL)) { + statement.setString(Column.DEFINED_BY, DefinedByType.USER.toString()); + statement.setInt(Column.TENANT_ID, tenantId); + + List allUserDefinedLocalConfigs = new ArrayList<>(); + try (ResultSet rs = statement.executeQuery()) { + while (rs.next()) { + UserDefinedLocalAuthenticatorConfig config = getLocalAuthenticatorConfigBasedOnType( + rs.getString(Column.AUTHENTICATION_TYPE)); + config.setName(rs.getString(Column.NAME)); + config.setDisplayName(rs.getString(Column.DISPLAY_NAME)); + config.setEnabled(rs.getString(Column.IS_ENABLED).equals(IS_TRUE_VALUE)); + config.setDefinedByType(DefinedByType.valueOf(rs.getString(Column.DEFINED_BY))); + allUserDefinedLocalConfigs.add(config); + } + } + + return allUserDefinedLocalConfigs; + } catch (SQLException e) { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Error while retrieving the all user defined local authenticators in tenant " + + "domain: %s.", IdentityTenantUtil.getTenantDomain(tenantId))); + } + ErrorMessages error = ErrorMessages.ERROR_WHILE_DELETING_AUTHENTICATOR; + throw new AuthenticatorMgtServerException(error.getMessage(), error.getMessage(), error.getCode(), e); + } + } + + @Override + public void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + Connection dbConnection = IdentityDatabaseUtil.getDBConnection(true); + try (NamedPreparedStatement statement = new NamedPreparedStatement(dbConnection, + Query.DELETE_AUTHENTICATOR_SQL)) { + statement.setString(Column.NAME, authenticatorConfigName); + statement.setInt(Column.TENANT_ID, tenantId); + statement.executeUpdate(); + + IdentityDatabaseUtil.commitTransaction(dbConnection); + } catch (SQLException e) { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Error while deleting the authenticator: %s in tenant domain: %s. " + + "Rolling back deleted Authenticator information.", authenticatorConfigName, + IdentityTenantUtil.getTenantDomain(tenantId))); + } + IdentityDatabaseUtil.rollbackTransaction(dbConnection); + ErrorMessages error = ErrorMessages.ERROR_WHILE_DELETING_AUTHENTICATOR; + throw new AuthenticatorMgtServerException(error.getMessage(), error.getMessage(), error.getCode(), e); + } finally { + IdentityDatabaseUtil.closeConnection(dbConnection); + } + } + + private UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticatorByName( + Connection dbConnection, String authenticatorConfigName, int tenantId) + throws AuthenticatorMgtServerException { + + UserDefinedLocalAuthenticatorConfig config = null; + try (NamedPreparedStatement statement = new NamedPreparedStatement(dbConnection, Query.GET_AUTHENTICATOR_SQL)) { + statement.setString(Column.NAME, authenticatorConfigName); + statement.setInt(Column.TENANT_ID, tenantId); + + try (ResultSet rs = statement.executeQuery()) { + if (rs.next()) { + config = getLocalAuthenticatorConfigBasedOnType(rs.getString(Column.AUTHENTICATION_TYPE)); + config.setName(rs.getString(Column.NAME)); + config.setDisplayName(rs.getString(Column.DISPLAY_NAME)); + config.setEnabled(rs.getString(Column.IS_ENABLED).equals(IS_TRUE_VALUE)); + config.setDefinedByType(DefinedByType.valueOf(rs.getString(Column.DEFINED_BY))); + } + } + + if (config == null) { + return null; + } + + int authenticatorConfigID = getAuthenticatorIdentifier(dbConnection, config.getName(), tenantId); + try (NamedPreparedStatement statementProp = new NamedPreparedStatement(dbConnection, + Query.GET_AUTHENTICATOR_PROP_SQL)) { + statementProp.setInt(Column.AUTHENTICATOR_ID, authenticatorConfigID); + statementProp.setInt(Column.TENANT_ID, tenantId); + + try (ResultSet rs = statementProp.executeQuery()) { + List properties = new ArrayList<>(); + while (rs.next()) { + Property property = new Property(); + property.setName(rs.getString(Column.PROPERTY_KEY)); + property.setValue(rs.getString(Column.PROPERTY_VALUE)); + property.setConfidential(Boolean.parseBoolean(rs.getString(Column.IS_SECRET))); + properties.add(property); + } + config.setProperties(properties.toArray(new Property[0])); + } + } + + IdentityDatabaseUtil.commitTransaction(dbConnection); + return config; + } catch (SQLException e) { + ErrorMessages error = ErrorMessages.ERROR_WHILE_RETRIEVING_AUTHENTICATOR_BY_NAME; + throw new AuthenticatorMgtServerException(error.getMessage(), error.getMessage(), error.getCode(), e); + } + } + + private UserDefinedLocalAuthenticatorConfig getLocalAuthenticatorConfigBasedOnType(String authenticationType) { + + if (AuthenticationType.VERIFICATION.toString().equals(authenticationType)) { + return new UserDefinedLocalAuthenticatorConfig(AuthenticationType.VERIFICATION); + } + return new UserDefinedLocalAuthenticatorConfig(AuthenticationType.IDENTIFICATION); + } + + private boolean isBasicInfoUpdated(UserDefinedLocalAuthenticatorConfig existingAuthenticatorConfig, + UserDefinedLocalAuthenticatorConfig updatedAuthenticatorConfig) { + + return !existingAuthenticatorConfig.getDisplayName().equals(updatedAuthenticatorConfig.getDisplayName()) || + existingAuthenticatorConfig.isEnabled() != updatedAuthenticatorConfig.isEnabled(); + } + + private int getAuthenticatorIdentifier(Connection dbConnection, String authenticatorConfigName, + int tenantId) throws AuthenticatorMgtServerException, SQLException { + + try (NamedPreparedStatement statement = new NamedPreparedStatement(dbConnection, + Query.GET_AUTHENTICATOR_ID_SQL)) { + statement.setString(Column.NAME, authenticatorConfigName); + statement.setInt(Column.TENANT_ID, tenantId); + + try (ResultSet rs = statement.executeQuery()) { + if (rs.next()) { + return rs.getInt(Column.ID); + } + } + IdentityDatabaseUtil.commitTransaction(dbConnection); + } + throw new AuthenticatorMgtServerException(String.format("Authenticator with name: %s not found in the database." + , authenticatorConfigName)); + } + + private void deletedAuthenticatorProperties(Connection dbConnection, int authenticatorConfigID, int tenantId) + throws SQLException { + + try (NamedPreparedStatement statementDeleteProp = new NamedPreparedStatement(dbConnection, + Query.DELETE_AUTHENTICATOR_PROP_SQL)) { + statementDeleteProp.setInt(Column.AUTHENTICATOR_ID, authenticatorConfigID); + statementDeleteProp.setInt(Column.TENANT_ID, tenantId); + statementDeleteProp.executeUpdate(); + } + } + + private void addAuthenticatorProperties(Connection dbConnection, int authenticatorConfigID, Property[] properties, + int tenantId) throws SQLException { + + try (NamedPreparedStatement statementProp = new NamedPreparedStatement(dbConnection, + Query.ADD_AUTHENTICATOR_PROP_SQL)) { + for (Property prop : properties) { + statementProp.setInt(Column.AUTHENTICATOR_ID, authenticatorConfigID); + statementProp.setInt(Column.TENANT_ID, tenantId); + statementProp.setString(Column.PROPERTY_KEY, prop.getName()); + statementProp.setString(Column.PROPERTY_VALUE, prop.getValue()); + if (prop.isConfidential()) { + statementProp.setString(Column.IS_SECRET, IS_TRUE_VALUE); + } else { + statementProp.setString(Column.IS_SECRET, IS_FALSE_VALUE); + } + statementProp.executeUpdate(); + } + } + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementFacade.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementFacade.java new file mode 100644 index 000000000000..17f24f22eca6 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/AuthenticatorManagementFacade.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.dao.impl; + +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.util.UserDefinedAuthenticatorEndpointConfigManager; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants; + +import java.util.List; + +/** + * This class responsible for managing authenticator endpoint configurations for the user defined local + * authenticators. + */ +public class AuthenticatorManagementFacade { + + private final AuthenticatorManagementDAOImpl dao; + private UserDefinedAuthenticatorEndpointConfigManager endpointConfigManager = + new UserDefinedAuthenticatorEndpointConfigManager(); + + public AuthenticatorManagementFacade(AuthenticatorManagementDAOImpl dao) { + + this.dao = dao; + } + + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, + int tenantId, AuthenticatorPropertyConstants.AuthenticationType type) throws AuthenticatorMgtException { + + endpointConfigManager.addEndpointConfigurations(authenticatorConfig, tenantId); + try { + return dao.addUserDefinedLocalAuthenticator(authenticatorConfig, tenantId, type); + } catch (AuthenticatorMgtException e) { + endpointConfigManager.deleteEndpointConfigurations(authenticatorConfig, tenantId); + throw e; + } + } + + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig + existingAuthenticatorConfig, UserDefinedLocalAuthenticatorConfig newAuthenticatorConfig, + int tenantId) throws AuthenticatorMgtException { + + endpointConfigManager.updateEndpointConfigurations(newAuthenticatorConfig, existingAuthenticatorConfig, + tenantId); + try { + return dao.updateUserDefinedLocalAuthenticator(existingAuthenticatorConfig, newAuthenticatorConfig, + tenantId); + } catch (AuthenticatorMgtException e) { + endpointConfigManager.updateEndpointConfigurations(existingAuthenticatorConfig, newAuthenticatorConfig, + tenantId); + throw e; + } + } + + public UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator( + String authenticatorConfigName, int tenantId) throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig config = dao.getUserDefinedLocalAuthenticator(authenticatorConfigName, + tenantId); + return endpointConfigManager.resolveEndpointConfigurations(config, tenantId); + } + + public List getAllUserDefinedLocalAuthenticator(int tenantId) + throws AuthenticatorMgtException { + + List configList = dao.getAllUserDefinedLocalAuthenticator(tenantId); + for (UserDefinedLocalAuthenticatorConfig config : configList) { + endpointConfigManager.resolveEndpointConfigurations(config, tenantId); + } + return configList; + } + + public void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, UserDefinedLocalAuthenticatorConfig + authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + endpointConfigManager.deleteEndpointConfigurations(authenticatorConfig, tenantId); + try { + dao.deleteUserDefinedLocalAuthenticator(authenticatorConfigName, authenticatorConfig, tenantId); + } catch (AuthenticatorMgtException e) { + endpointConfigManager.addEndpointConfigurations(authenticatorConfig, tenantId); + throw e; + } + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/CacheBackedAuthenticatorMgtDAO.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/CacheBackedAuthenticatorMgtDAO.java new file mode 100644 index 000000000000..6fe0c715adbf --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/dao/impl/CacheBackedAuthenticatorMgtDAO.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.identity.application.common.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.common.cache.AuthenticatorCache; +import org.wso2.carbon.identity.application.common.cache.AuthenticatorCacheEntry; +import org.wso2.carbon.identity.application.common.cache.AuthenticatorCacheKey; +import org.wso2.carbon.identity.application.common.dao.AuthenticatorManagementDAO; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.AuthenticationType; + +import java.util.List; + +/** + * This class implements the Cache backed AuthenticatorManagementDAO interface. + */ +public class CacheBackedAuthenticatorMgtDAO implements AuthenticatorManagementDAO { + + private static final Log LOG = LogFactory.getLog(CacheBackedAuthenticatorMgtDAO.class); + private final AuthenticatorCache authenticatorCache; + private final AuthenticatorManagementDAO authenticatorManagementDAO; + + public CacheBackedAuthenticatorMgtDAO(AuthenticatorManagementDAO authenticatorManagementDAO) { + + this.authenticatorManagementDAO = authenticatorManagementDAO; + authenticatorCache = AuthenticatorCache.getInstance(); + } + + @Override + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, + int tenantId, AuthenticationType type) throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig createdConfig = authenticatorManagementDAO.addUserDefinedLocalAuthenticator( + authenticatorConfig, tenantId, type); + + AuthenticatorCacheKey cacheKey = new AuthenticatorCacheKey(authenticatorConfig.getName()); + authenticatorCache.addToCache(cacheKey, new AuthenticatorCacheEntry(createdConfig), tenantId); + return createdConfig; + } + + @Override + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig + existingAuthenticatorConfig, UserDefinedLocalAuthenticatorConfig newAuthenticatorConfig, + int tenantId) throws AuthenticatorMgtException { + + AuthenticatorCacheKey cacheKey = new AuthenticatorCacheKey(existingAuthenticatorConfig.getName()); + authenticatorCache.clearCacheEntry(cacheKey, tenantId); + + return authenticatorManagementDAO.updateUserDefinedLocalAuthenticator( + existingAuthenticatorConfig, newAuthenticatorConfig, tenantId); + } + + @Override + public UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator( + String authenticatorConfigName, int tenantId) throws AuthenticatorMgtException { + + AuthenticatorCacheKey cacheKey = new AuthenticatorCacheKey(authenticatorConfigName); + AuthenticatorCacheEntry entry = authenticatorCache.getValueFromCache(cacheKey, tenantId); + + if (entry != null) { + return entry.getAuthenticatorConfig(); + } + + return authenticatorManagementDAO.getUserDefinedLocalAuthenticator(authenticatorConfigName, tenantId); + } + + @Override + public List getAllUserDefinedLocalAuthenticator(int tenantId) + throws AuthenticatorMgtException { + + return authenticatorManagementDAO.getAllUserDefinedLocalAuthenticator(tenantId); + } + + @Override + public void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + authenticatorCache.clearCacheEntry(new AuthenticatorCacheKey(authenticatorConfigName), tenantId); + authenticatorManagementDAO.deleteUserDefinedLocalAuthenticator(authenticatorConfigName, authenticatorConfig, + tenantId); + } +}