diff --git a/components/action-mgt/org.wso2.carbon.identity.action.execution/pom.xml b/components/action-mgt/org.wso2.carbon.identity.action.execution/pom.xml index f6ea54415982..656abf0901ff 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.execution/pom.xml +++ b/components/action-mgt/org.wso2.carbon.identity.action.execution/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework action-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/pom.xml b/components/action-mgt/org.wso2.carbon.identity.action.management/pom.xml index 832acc06912b..afb6b8f736d7 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/pom.xml +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework action-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml @@ -89,7 +89,6 @@ ${project.artifactId} - org.wso2.carbon.identity.action.management.cache, org.wso2.carbon.identity.action.management.constant, org.wso2.carbon.identity.action.management.dao.*, org.wso2.carbon.identity.action.management.internal, @@ -97,6 +96,7 @@ org.wso2.carbon.identity.action.management.util + org.wso2.carbon.identity.action.management.cache, org.wso2.carbon.identity.action.management.constant.error, org.wso2.carbon.identity.action.management.exception, org.wso2.carbon.identity.action.management.model, diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionCacheEntry.java b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionCacheEntry.java index 4ed821e43765..cec36a14b47a 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionCacheEntry.java +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionCacheEntry.java @@ -28,6 +28,7 @@ */ public class ActionCacheEntry extends CacheEntry { + private static final long serialVersionUID = 2789265346825849739L; private List actionsOfActionType; public ActionCacheEntry(List actionsOfActionType) { diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionTypeCacheKey.java b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionTypeCacheKey.java index 98fd51cf3dfc..76609a0e866d 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionTypeCacheKey.java +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/cache/ActionTypeCacheKey.java @@ -25,6 +25,7 @@ */ public class ActionTypeCacheKey extends CacheKey { + private static final long serialVersionUID = 8132735629148475983L; private final String actionType; public ActionTypeCacheKey(String actionType) { diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/constant/ActionMgtSQLConstants.java b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/constant/ActionMgtSQLConstants.java index 6fecc776c47d..8f6ae2c77200 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/constant/ActionMgtSQLConstants.java +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/constant/ActionMgtSQLConstants.java @@ -27,9 +27,6 @@ private ActionMgtSQLConstants() { } - public static final String IDN_ACTION_PROPERTIES_TABLE = "IDN_ACTION_PROPERTIES"; - public static final String IDN_ACTION_ENDPOINT_TABLE = "IDN_ACTION_ENDPOINT"; - /** * Column Names. */ @@ -81,19 +78,6 @@ public static class Query { "PROPERTY_VALUE = :PROPERTY_VALUE; WHERE ACTION_UUID = :ACTION_UUID; AND " + "TENANT_ID = :TENANT_ID; AND PROPERTY_NAME = :PROPERTY_NAME;"; - // TODO: Remove this temporary queries once the IDN_ACTION_PROPERTIES table is created. - public static final String ADD_ACTION_ENDPOINT = "INSERT INTO IDN_ACTION_ENDPOINT (ACTION_UUID, " + - "PROPERTY_NAME, PROPERTY_VALUE, TENANT_ID) VALUES (:ACTION_UUID;, :PROPERTY_NAME;, :PROPERTY_VALUE;, " + - ":TENANT_ID;)"; - public static final String GET_ACTION_ENDPOINT_INFO_BY_ID = "SELECT PROPERTY_NAME, PROPERTY_VALUE FROM " + - "IDN_ACTION_ENDPOINT WHERE ACTION_UUID = :ACTION_UUID; AND TENANT_ID = :TENANT_ID;"; - public static final String DELETE_ACTION_ENDPOINT_PROPERTY = "DELETE FROM IDN_ACTION_ENDPOINT WHERE " + - "PROPERTY_NAME = :PROPERTY_NAME; AND ACTION_UUID = :ACTION_UUID; AND TENANT_ID = :TENANT_ID;"; - public static final String UPDATE_ACTION_ENDPOINT_PROPERTY = "UPDATE IDN_ACTION_ENDPOINT SET " + - "PROPERTY_VALUE = :PROPERTY_VALUE; WHERE ACTION_UUID = :ACTION_UUID; AND " + - "TENANT_ID = :TENANT_ID; AND PROPERTY_NAME = :PROPERTY_NAME;"; - - private Query() { } diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/dao/impl/ActionManagementDAOImpl.java b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/dao/impl/ActionManagementDAOImpl.java index 2a53f6b1e810..59850e7efc8d 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/dao/impl/ActionManagementDAOImpl.java +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/dao/impl/ActionManagementDAOImpl.java @@ -20,7 +20,6 @@ import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; import org.wso2.carbon.database.utils.jdbc.NamedPreparedStatement; -import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; import org.wso2.carbon.identity.action.management.constant.ActionMgtSQLConstants; import org.wso2.carbon.identity.action.management.dao.ActionManagementDAO; @@ -162,15 +161,16 @@ public Map getActionsCountPerType(Integer tenantId) throws Acti Map actionTypesCountMap = new HashMap<>(); NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); try { - jdbcTemplate.executeQuery(ActionMgtSQLConstants.Query.GET_ACTIONS_COUNT_PER_ACTION_TYPE, - (resultSet, rowNumber) -> { - actionTypesCountMap.put(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_TYPE), - resultSet.getInt(ActionMgtSQLConstants.Column.ACTION_COUNT)); - return null; - }, statement -> statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId)); + jdbcTemplate.withTransaction(template -> + template.executeQuery(ActionMgtSQLConstants.Query.GET_ACTIONS_COUNT_PER_ACTION_TYPE, + (resultSet, rowNumber) -> { + actionTypesCountMap.put(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_TYPE), + resultSet.getInt(ActionMgtSQLConstants.Column.ACTION_COUNT)); + return null; + }, statement -> statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId))); return actionTypesCountMap; - } catch (DataAccessException e) { + } catch (TransactionException e) { throw new ActionMgtServerException("Error while retrieving Actions count per Action Type from the system.", e); } @@ -187,22 +187,19 @@ private void addBasicInfo(ActionDTO actionDTO, Integer tenantId) throws ActionMg NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); try { - jdbcTemplate.withTransaction(template -> { + jdbcTemplate.withTransaction(template -> template.executeInsert(ActionMgtSQLConstants.Query.ADD_ACTION_TO_ACTION_TYPE, - statement -> { - statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, actionDTO.getId()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, - actionDTO.getType().getActionType()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_NAME, actionDTO.getName()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_DESCRIPTION, - actionDTO.getDescription()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_STATUS, - String.valueOf( - org.wso2.carbon.identity.action.management.model.Action.Status.ACTIVE)); - statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); - }, actionDTO, false); - return null; - }); + statement -> { + statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, actionDTO.getId()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, + actionDTO.getType().getActionType()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_NAME, actionDTO.getName()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_DESCRIPTION, + actionDTO.getDescription()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_STATUS, + String.valueOf(Action.Status.ACTIVE)); + statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); + }, actionDTO, false)); } catch (TransactionException e) { throw new ActionMgtServerException("Error while adding Action Basic information in the system.", e); } @@ -225,19 +222,24 @@ private void updateBasicInfo(ActionDTO updatingActionDTO, ActionDTO existingActi NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); try { - jdbcTemplate.executeUpdate(ActionMgtSQLConstants.Query.UPDATE_ACTION_BASIC_INFO, - statement -> { - statement.setString(ActionMgtSQLConstants.Column.ACTION_NAME, updatingActionDTO.getName() == null ? - existingActionDTO.getName() : updatingActionDTO.getName()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_DESCRIPTION, - updatingActionDTO.getDescription() == null ? existingActionDTO.getDescription() - : updatingActionDTO.getDescription()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, updatingActionDTO.getId()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, - updatingActionDTO.getType().getActionType()); - statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(ActionMgtSQLConstants.Query.UPDATE_ACTION_BASIC_INFO, + statement -> { + statement.setString(ActionMgtSQLConstants.Column.ACTION_NAME, + updatingActionDTO.getName() == null ? existingActionDTO.getName() + : updatingActionDTO.getName()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_DESCRIPTION, + updatingActionDTO.getDescription() == null ? existingActionDTO.getDescription() + : updatingActionDTO.getDescription()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, updatingActionDTO.getId()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, + updatingActionDTO.getType().getActionType()); + statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); }); - } catch (DataAccessException e) { + + return null; + }); + } catch (TransactionException e) { throw new ActionMgtServerException("Error while updating Action Basic information in the system.", e); } } @@ -255,19 +257,22 @@ private ActionDTOBuilder getBasicInfo(String actionType, String actionId, Intege NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); try { - return jdbcTemplate.fetchSingleRecord(ActionMgtSQLConstants.Query.GET_ACTION_BASIC_INFO_BY_ID, - (resultSet, rowNumber) -> new ActionDTOBuilder() - .id(actionId) - .type(Action.ActionTypes.valueOf(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_TYPE))) - .name(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_NAME)) - .description(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_DESCRIPTION)) - .status(Action.Status.valueOf(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_STATUS))), - statement -> { - statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, actionType); - statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, actionId); - statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); - }); - } catch (DataAccessException e) { + return jdbcTemplate.withTransaction(template -> + template.fetchSingleRecord(ActionMgtSQLConstants.Query.GET_ACTION_BASIC_INFO_BY_ID, + (resultSet, rowNumber) -> new ActionDTOBuilder() + .id(actionId) + .type(Action.ActionTypes.valueOf( + resultSet.getString(ActionMgtSQLConstants.Column.ACTION_TYPE))) + .name(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_NAME)) + .description(resultSet.getString(ActionMgtSQLConstants.Column.ACTION_DESCRIPTION)) + .status(Action.Status.valueOf( + resultSet.getString(ActionMgtSQLConstants.Column.ACTION_STATUS))), + statement -> { + statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, actionType); + statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, actionId); + statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); + })); + } catch (TransactionException e) { throw new ActionMgtServerException("Error while retrieving Action Basic information from the system.", e); } } @@ -475,9 +480,7 @@ private void addActionPropertiesToDB(String actionId, Map action NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); jdbcTemplate.withTransaction(template -> { - String query = isPropertiesTableExists() ? ActionMgtSQLConstants.Query.ADD_ACTION_PROPERTIES - : ActionMgtSQLConstants.Query.ADD_ACTION_ENDPOINT; - template.executeBatchInsert(query, + template.executeBatchInsert(ActionMgtSQLConstants.Query.ADD_ACTION_PROPERTIES, statement -> { for (Map.Entry property : actionProperties.entrySet()) { statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_UUID, actionId); @@ -506,22 +509,21 @@ private Map getActionPropertiesFromDB(String actionId, Integer t NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); Map actionEndpointProperties = new HashMap<>(); try { - String query = isPropertiesTableExists() ? ActionMgtSQLConstants.Query.GET_ACTION_PROPERTIES_INFO_BY_ID - : ActionMgtSQLConstants.Query.GET_ACTION_ENDPOINT_INFO_BY_ID; - jdbcTemplate.executeQuery(query, - (resultSet, rowNumber) -> { - actionEndpointProperties.put( - resultSet.getString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_NAME), - resultSet.getString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_VALUE)); - return null; - }, - statement -> { - statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_UUID, actionId); - statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); - }); + jdbcTemplate.withTransaction(template -> + template.executeQuery(ActionMgtSQLConstants.Query.GET_ACTION_PROPERTIES_INFO_BY_ID, + (resultSet, rowNumber) -> { + actionEndpointProperties.put( + resultSet.getString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_NAME), + resultSet.getString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_VALUE)); + return null; + }, + statement -> { + statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_UUID, actionId); + statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); + })); return actionEndpointProperties; - } catch (DataAccessException | SQLException e) { + } catch (TransactionException e) { throw new ActionMgtServerException("Error while retrieving Action Properties from the system.", e); } } @@ -538,22 +540,19 @@ private void updateActionPropertiesInDB(String actionId, Map upd Integer tenantId) throws TransactionException { NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); - jdbcTemplate.withTransaction(template -> { - String query = isPropertiesTableExists() ? ActionMgtSQLConstants.Query.UPDATE_ACTION_PROPERTY - : ActionMgtSQLConstants.Query.UPDATE_ACTION_ENDPOINT_PROPERTY; - return template.executeBatchInsert(query, - statement -> { - for (Map.Entry property : updatingProperties.entrySet()) { - statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_VALUE, - property.getValue()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_NAME, - property.getKey()); - statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_UUID, actionId); - statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); - statement.addBatch(); - } - }, null); - }); + jdbcTemplate.withTransaction(template -> + template.executeBatchInsert(ActionMgtSQLConstants.Query.UPDATE_ACTION_PROPERTY, + statement -> { + for (Map.Entry property : updatingProperties.entrySet()) { + statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_VALUE, + property.getValue()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_NAME, + property.getKey()); + statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_UUID, actionId); + statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); + statement.addBatch(); + } + }, null)); } /** @@ -568,10 +567,8 @@ private void deleteActionPropertiesInDB(String actionId, List deletingPr throws TransactionException { NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); - jdbcTemplate.withTransaction(template -> { - String query = isPropertiesTableExists() ? ActionMgtSQLConstants.Query.DELETE_ACTION_PROPERTY - : ActionMgtSQLConstants.Query.DELETE_ACTION_ENDPOINT_PROPERTY; - return template.executeBatchInsert(query, + jdbcTemplate.withTransaction(template -> + template.executeBatchInsert(ActionMgtSQLConstants.Query.DELETE_ACTION_PROPERTY, statement -> { for (String property : deletingProperties) { statement.setString(ActionMgtSQLConstants.Column.ACTION_PROPERTIES_PROPERTY_NAME, @@ -580,8 +577,7 @@ private void deleteActionPropertiesInDB(String actionId, List deletingPr statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); statement.addBatch(); } - }, null); - }); + }, null)); } /** @@ -599,33 +595,21 @@ private ActionDTO changeActionStatus(String actionType, String actionId, String NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); try { - jdbcTemplate.executeUpdate(ActionMgtSQLConstants.Query.CHANGE_ACTION_STATUS, - statement -> { - statement.setString(ActionMgtSQLConstants.Column.ACTION_STATUS, status); - statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, actionId); - statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, actionType); - statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); - }); + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(ActionMgtSQLConstants.Query.CHANGE_ACTION_STATUS, + statement -> { + statement.setString(ActionMgtSQLConstants.Column.ACTION_STATUS, status); + statement.setString(ActionMgtSQLConstants.Column.ACTION_UUID, actionId); + statement.setString(ActionMgtSQLConstants.Column.ACTION_TYPE, actionType); + statement.setInt(ActionMgtSQLConstants.Column.TENANT_ID, tenantId); + }); + + return null; + }); return getBasicInfo(actionType, actionId, tenantId).build(); - } catch (DataAccessException e) { + } catch (TransactionException e) { throw new ActionMgtServerException("Error while updating Action Status to " + status, e); } } - - /** - * Check whether the IDN_ACTION_PROPERTIES table exists in the database. - * TODO: Remove this temporary method once the table is created. - * - * @return True if the table exists, False otherwise. - * @throws SQLException If an error occurs while checking the table existence. - */ - private boolean isPropertiesTableExists() throws SQLException { - - try (Connection connection = IdentityDatabaseUtil.getDBConnection(false); - ResultSet resultSet = connection.getMetaData().getTables(null, null, - ActionMgtSQLConstants.IDN_ACTION_PROPERTIES_TABLE, null)) { - return resultSet.next(); - } - } } diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/service/impl/ActionManagementServiceImpl.java b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/service/impl/ActionManagementServiceImpl.java index 829930197a74..aaa8168b30e0 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/service/impl/ActionManagementServiceImpl.java +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/main/java/org/wso2/carbon/identity/action/management/service/impl/ActionManagementServiceImpl.java @@ -175,10 +175,12 @@ public void deleteAction(String actionType, String actionId, String tenantDomain if (LOG.isDebugEnabled()) { LOG.debug(String.format("Deleting Action for Action Type: %s and Action ID: %s", actionType, actionId)); } - String resolvedActionType = getActionTypeFromPath(actionType); - ActionDTO existingActionDTO = checkIfActionExists(resolvedActionType, actionId, tenantDomain); - DAO_FACADE.deleteAction(existingActionDTO, IdentityTenantUtil.getTenantId(tenantDomain)); - auditLogger.printAuditLog(ActionManagementAuditLogger.Operation.DELETE, actionType, actionId); + ActionDTO existingActionDTO = DAO_FACADE.getActionByActionId(getActionTypeFromPath(actionType), actionId, + IdentityTenantUtil.getTenantId(tenantDomain)); + if (existingActionDTO != null) { + DAO_FACADE.deleteAction(existingActionDTO, IdentityTenantUtil.getTenantId(tenantDomain)); + auditLogger.printAuditLog(ActionManagementAuditLogger.Operation.DELETE, actionType, actionId); + } } /** diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/java/org/wso2/carbon/identity/action/management/service/ActionManagementServiceImplTest.java b/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/java/org/wso2/carbon/identity/action/management/service/ActionManagementServiceImplTest.java index aa6b55351516..1d159ec3bcde 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/java/org/wso2/carbon/identity/action/management/service/ActionManagementServiceImplTest.java +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/java/org/wso2/carbon/identity/action/management/service/ActionManagementServiceImplTest.java @@ -310,6 +310,16 @@ public void testDeleteAction() throws ActionMgtException { Assert.assertNull(actions.get(PRE_ISSUE_ACCESS_TOKEN_PATH)); } + @Test(priority = 14) + public void testDeleteNonExistingAction() { + + try { + actionManagementService.deleteAction(PRE_ISSUE_ACCESS_TOKEN_PATH, "invalid_id", TENANT_DOMAIN); + } catch (Exception e) { + Assert.fail(); + } + } + private Map resolveAuthPropertiesMap(Authentication authentication, String actionId) throws SecretManagementException { diff --git a/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/resources/dbscripts/h2.sql b/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/resources/dbscripts/h2.sql index 776921371a60..9bf8470be8e8 100644 --- a/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/resources/dbscripts/h2.sql +++ b/components/action-mgt/org.wso2.carbon.identity.action.management/src/test/resources/dbscripts/h2.sql @@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS IDN_ACTION ( PRIMARY KEY (UUID) ); -CREATE TABLE IF NOT EXISTS IDN_ACTION_ENDPOINT ( +CREATE TABLE IF NOT EXISTS IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, diff --git a/components/action-mgt/pom.xml b/components/action-mgt/pom.xml index 9e3bdd330920..fb4b12a21ad6 100644 --- a/components/action-mgt/pom.xml +++ b/components/action-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.collection.mgt/pom.xml b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.collection.mgt/pom.xml index d48870284d01..71708af51112 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.collection.mgt/pom.xml +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.collection.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework api-resource-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml index b779b256b82a..0de2cc120656 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework api-resource-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml org.wso2.carbon.identity.api.resource.mgt diff --git a/components/api-resource-mgt/pom.xml b/components/api-resource-mgt/pom.xml index d769be8935fc..d3348394434f 100644 --- a/components/api-resource-mgt/pom.xml +++ b/components/api-resource-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/pom.xml b/components/application-mgt/org.wso2.carbon.identity.application.common/pom.xml index f77be6070630..5bcad9698607 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/pom.xml +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/pom.xml @@ -18,7 +18,7 @@ org.wso2.carbon.identity.framework application-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml @@ -61,6 +61,21 @@ org.wso2.carbon.identity.framework org.wso2.carbon.identity.central.log.mgt + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.testutil + test + + + org.mockito + mockito-core + test + + + com.h2database + h2 + test + org.wso2.carbon.identity.framework org.wso2.carbon.identity.action.management @@ -90,7 +105,11 @@ org.apache.axiom.*; version="${axiom.osgi.version.range}", org.apache.commons.logging; version="${import.package.version.commons.logging}", org.apache.commons.lang; version="${commons-lang.wso2.osgi.version.range}", + org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", org.apache.commons.collections; version="${commons-collections.wso2.osgi.version.range}", + org.wso2.carbon.database.utils.jdbc; version="${org.wso2.carbon.database.utils.version.range}", + org.wso2.carbon.database.utils.jdbc.exceptions; version="${org.wso2.carbon.database.utils.version.range}", org.apache.axis2.*; version="${axis2.osgi.version.range}", diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/ApplicationAuthenticatorService.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/ApplicationAuthenticatorService.java index e93a82f42b75..92674282267c 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/ApplicationAuthenticatorService.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/ApplicationAuthenticatorService.java @@ -18,23 +18,43 @@ package org.wso2.carbon.identity.application.common; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.common.dao.AuthenticatorManagementDAO; +import org.wso2.carbon.identity.application.common.dao.impl.AuthenticatorManagementDAOImpl; +import org.wso2.carbon.identity.application.common.dao.impl.CacheBackedAuthenticatorMgtDAO; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig; import org.wso2.carbon.identity.application.common.model.LocalAuthenticatorConfig; import org.wso2.carbon.identity.application.common.model.RequestPathAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError; +import org.wso2.carbon.identity.application.common.util.UserDefinedLocalAuthenticatorValidator; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import java.util.ArrayList; import java.util.List; +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.buildClientException; +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.buildRuntimeServerException; +import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Authenticator.DISPLAY_NAME; + /** * Application authenticator service. */ public class ApplicationAuthenticatorService { private static volatile ApplicationAuthenticatorService instance; + private static final Log LOG = LogFactory.getLog(ApplicationAuthenticatorService.class); + private static final AuthenticatorManagementDAO dao = + new CacheBackedAuthenticatorMgtDAO(new AuthenticatorManagementDAOImpl()); private List localAuthenticators = new ArrayList<>(); private List federatedAuthenticators = new ArrayList<>(); private List requestPathAuthenticators = new ArrayList<>(); + private UserDefinedLocalAuthenticatorValidator authenticatorValidator = + new UserDefinedLocalAuthenticatorValidator(); public static ApplicationAuthenticatorService getInstance() { if (instance == null) { @@ -51,6 +71,18 @@ public List getLocalAuthenticators() { return this.localAuthenticators; } + /** + * This returns user defined local authenticators. + * + * @param tenantDomain Tenant domain. + * @return Retrieved LocalAuthenticatorConfig. + */ + public List getAllUserDefinedLocalAuthenticators(String tenantDomain) + throws AuthenticatorMgtException { + + return dao.getAllUserDefinedLocalAuthenticators(IdentityTenantUtil.getTenantId(tenantDomain)); + } + public List getFederatedAuthenticators() { return this.federatedAuthenticators; } @@ -59,6 +91,16 @@ public List getRequestPathAuthenticators() { return this.requestPathAuthenticators; } + /** + * This returns only SYSTEM defined local authenticator by name. + * + * @param name The name of the Local Application Authenticator configuration. + * @return Retrieved LocalAuthenticatorConfig. + * + * @deprecated It is recommended to use {@link #getLocalAuthenticatorByName(String, String)}, + * which supports retrieving both USER and SYSTEM defined Local Application Authenticator configuration by name. + */ + @Deprecated public LocalAuthenticatorConfig getLocalAuthenticatorByName(String name) { for (LocalAuthenticatorConfig localAuthenticator : localAuthenticators) { if (localAuthenticator.getName().equals(name)) { @@ -68,6 +110,27 @@ public LocalAuthenticatorConfig getLocalAuthenticatorByName(String name) { return null; } + /** + * Retrieve both USER and SYSTEM defined Local Application Authenticator configuration by name. + * + * @param name The name of the Local Application Authenticator configuration. + * @param tenantDomain Tenant domain. + * @return Retrieved LocalAuthenticatorConfig. + * @throws AuthenticatorMgtException If an error occurs while retrieving the authenticator configuration by name. + */ + public LocalAuthenticatorConfig getLocalAuthenticatorByName(String name, String tenantDomain) + throws AuthenticatorMgtException { + + /* First, check whether an authenticator by the given name is in the system defined authenticators list. + If not, check in user defined authenticators. */ + for (LocalAuthenticatorConfig localAuthenticator : localAuthenticators) { + if (localAuthenticator.getName().equals(name)) { + return localAuthenticator; + } + } + return getUserDefinedLocalAuthenticator(name, tenantDomain); + } + public FederatedAuthenticatorConfig getFederatedAuthenticatorByName(String name) { for (FederatedAuthenticatorConfig federatedAuthenticator : federatedAuthenticators) { if (federatedAuthenticator.getName().equals(name)) { @@ -86,8 +149,18 @@ public RequestPathAuthenticatorConfig getRequestPathAuthenticatorByName(String n return null; } + /** + * Add a system defined Local Application Authenticator configuration. + * + * @param authenticator The Local Application Authenticator configuration. + */ public void addLocalAuthenticator(LocalAuthenticatorConfig authenticator) { + if (authenticator != null) { + if (authenticator.getDefinedByType() != DefinedByType.SYSTEM) { + throw buildRuntimeServerException( + AuthenticatorMgtError.ERROR_CODE_INVALID_DEFINED_BY_AUTH_PROVIDED, null); + } localAuthenticators.add(authenticator); } } @@ -121,4 +194,94 @@ public void removeRequestPathAuthenticator(RequestPathAuthenticatorConfig authen requestPathAuthenticators.remove(authenticator); } } + + /** + * Create a user defined Local Application Authenticator configuration. + * + * @param authenticatorConfig The Local Application Authenticator configuration. + * @param tenantDomain Tenant domain. + * @return Updated LocalAuthenticatorConfig. + * @throws AuthenticatorMgtException If an error occurs while creating the authenticator configuration. + */ + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, String tenantDomain) + throws AuthenticatorMgtException { + + LocalAuthenticatorConfig config = getLocalAuthenticatorByName(authenticatorConfig.getName(), tenantDomain); + if (config != null) { + throw buildClientException(AuthenticatorMgtError.ERROR_AUTHENTICATOR_ALREADY_EXIST, + authenticatorConfig.getName()); + } + authenticatorValidator.validateAuthenticatorName(authenticatorConfig.getName()); + authenticatorValidator.validateForBlank(DISPLAY_NAME, authenticatorConfig.getDisplayName()); + + return dao.addUserDefinedLocalAuthenticator( + authenticatorConfig, IdentityTenantUtil.getTenantId(tenantDomain)); + } + + /** + * Update a user defined Local Application Authenticator configuration. + * + * @param authenticatorConfig The Local Application Authenticator configuration. + * @param tenantDomain Tenant Domain. + * @return Updated UserDefinedLocalAuthenticatorConfig. + * @throws AuthenticatorMgtException If an error occurs while updating the authenticator configuration. + */ + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, String tenantDomain) + throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig existingConfig = resolveExistingAuthenticator( + authenticatorConfig.getName(), tenantDomain); + if (existingConfig == null) { + throw buildClientException(AuthenticatorMgtError.ERROR_NOT_FOUND_AUTHENTICATOR, + authenticatorConfig.getName()); + } + + authenticatorValidator.validateForBlank(DISPLAY_NAME, authenticatorConfig.getDisplayName()); + + return dao.updateUserDefinedLocalAuthenticator( + existingConfig, authenticatorConfig, IdentityTenantUtil.getTenantId(tenantDomain)); + } + + /** + * Update a Local Application Authenticator configuration. + * + * @param authenticatorName Name of Local Application Authenticator configuration to be deleted. + * @param tenantDomain Tenant domain. + * @throws AuthenticatorMgtException If an error occurs while deleting the authenticator configuration. + */ + public void deleteUserDefinedLocalAuthenticator(String authenticatorName, String tenantDomain) + throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig existingConfig = resolveExistingAuthenticator( + authenticatorName, tenantDomain); + if (existingConfig == null) { + return; + } + + dao.deleteUserDefinedLocalAuthenticator(authenticatorName, existingConfig, + IdentityTenantUtil.getTenantId(tenantDomain)); + } + + /** + * Retrieve a Local Application Authenticator configuration by name. + * + * @param authenticatorName Name of Local Application Authenticator configuration to be deleted. + * @param tenantDomain Tenant domain. + * @return Retrieved UserDefinedLocalAuthenticatorConfig. + * @throws AuthenticatorMgtException If an error occurs while retrieving the authenticator configuration. + */ + public UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator(String authenticatorName, + String tenantDomain) throws AuthenticatorMgtException { + + return dao.getUserDefinedLocalAuthenticator( + authenticatorName, IdentityTenantUtil.getTenantId(tenantDomain)); + } + + private UserDefinedLocalAuthenticatorConfig resolveExistingAuthenticator(String authenticatorName, + String tenantDomain) throws AuthenticatorMgtException { + + return dao.getUserDefinedLocalAuthenticator(authenticatorName, IdentityTenantUtil.getTenantId(tenantDomain)); + } } 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..b1495a2f30db --- /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 user defined 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..9529cd3aba92 --- /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,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.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 static final long serialVersionUID = -6234723984328871924L; + + 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..645fda5227af --- /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,56 @@ +/* + * 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 user defined local application authenticator configurations. + */ +public class AuthenticatorCacheKey extends CacheKey { + + private static final long serialVersionUID = -2897123859023483921L; + + 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..6269a541810b --- /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 DEFINED_BY = :DEFINED_BY; AND 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..292a22192948 --- /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,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.dao; + +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; + +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) 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 getAllUserDefinedLocalAuthenticators(int tenantId) + throws AuthenticatorMgtException; + + /** + * Create a new user defined 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..e04a7f860487 --- /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,284 @@ +/* + * 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.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +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.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError; +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 java.util.ArrayList; +import java.util.List; + +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.buildServerException; + +/** + * This class implements the AuthenticatorManagementDAO interface which perform CRUD operation on database. + */ +public class AuthenticatorManagementDAOImpl implements AuthenticatorManagementDAO { + + private static final String IS_TRUE_VALUE = "1"; + private static final String IS_FALSE_VALUE = "0"; + private static final String LOCAL_IDP_NAME = "LOCAL"; + + @Override + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + int authenticatorConfigID = jdbcTemplate.withTransaction(template -> + template.executeInsert(Query.ADD_AUTHENTICATOR_SQL, + statement -> { + 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, authenticatorConfig.getAuthenticationType() + .toString()); + statement.setString(Column.IS_ENABLED, + authenticatorConfig.isEnabled() ? IS_TRUE_VALUE : IS_FALSE_VALUE); + statement.setString(Column.IDP_NAME, LOCAL_IDP_NAME); + statement.setInt(Column.TENANT_ID, tenantId); + }, null, true)); + + if (authenticatorConfigID == 0) { + authenticatorConfigID = getAuthenticatorEntryId(authenticatorConfig.getName(), tenantId); + } + addAuthenticatorProperty(authenticatorConfigID, authenticatorConfig.getProperties(), tenantId); + + return getUserDefinedLocalAuthenticatorByName(authenticatorConfig.getName(), tenantId); + } catch (TransactionException e) { + throw buildServerException(AuthenticatorMgtError.ERROR_WHILE_ADDING_AUTHENTICATOR, e); + } + } + + @Override + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig existingAuthenticatorConfig, + UserDefinedLocalAuthenticatorConfig updatedAuthenticatorConfig, int tenantId) + throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(Query.UPDATE_AUTHENTICATOR_SQL, + statement -> { + statement.setString(Column.DISPLAY_NAME, updatedAuthenticatorConfig.getDisplayName()); + statement.setString(Column.IS_ENABLED, + updatedAuthenticatorConfig.isEnabled() ? IS_TRUE_VALUE : IS_FALSE_VALUE); + statement.setString(Column.NAME, existingAuthenticatorConfig.getName()); + statement.setInt(Column.TENANT_ID, tenantId); + }); + return null; + }); + + return getUserDefinedLocalAuthenticatorByName(updatedAuthenticatorConfig.getName(), tenantId); + } catch (TransactionException e) { + throw buildServerException(AuthenticatorMgtError.ERROR_WHILE_UPDATING_AUTHENTICATOR, e); + } + } + + @Override + public UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator( + String authenticatorConfigName, int tenantId) throws AuthenticatorMgtException { + + try { + return getUserDefinedLocalAuthenticatorByName(authenticatorConfigName, tenantId); + } catch (TransactionException e) { + throw buildServerException(AuthenticatorMgtError.ERROR_WHILE_RETRIEVING_AUTHENTICATOR_BY_NAME, e); + } + } + + @Override + public List getAllUserDefinedLocalAuthenticators(int tenantId) + throws AuthenticatorMgtException { + + try { + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + List allUserDefinedLocalConfigs = new ArrayList<>(); + List configDaoModels = jdbcTemplate.withTransaction( + template -> template.executeQuery(Query.GET_ALL_USER_DEFINED_AUTHENTICATOR_SQL, + (resultSet, rowNumber) -> { + UserDefinedLocalAuthenticatorConfig config = getLocalAuthenticatorConfigBasedOnType( + resultSet.getString(Column.AUTHENTICATION_TYPE)); + config.setName(resultSet.getString(Column.NAME)); + config.setDisplayName(resultSet.getString(Column.DISPLAY_NAME)); + config.setEnabled(resultSet.getString(Column.IS_ENABLED).equals(IS_TRUE_VALUE)); + config.setDefinedByType(DefinedByType.valueOf(resultSet.getString(Column.DEFINED_BY))); + return new AuthenticatorConfigDaoModel(resultSet.getInt(Column.ID), config); + }, + statement -> { + statement.setString(Column.DEFINED_BY, DefinedByType.USER.toString()); + statement.setInt(Column.TENANT_ID, tenantId); + })); + + for (AuthenticatorConfigDaoModel config: configDaoModels) { + UserDefinedLocalAuthenticatorConfig retrievedConfigs = config.getConfig(); + retrievedConfigs.setProperties(getAuthenticatorProperties(config.getEntryId(), tenantId)); + allUserDefinedLocalConfigs.add(retrievedConfigs); + } + return allUserDefinedLocalConfigs; + } catch (TransactionException e) { + throw buildServerException(AuthenticatorMgtError.ERROR_WHILE_RETRIEVING_AUTHENTICATOR_BY_NAME, e); + } + } + + @Override + public void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(Query.DELETE_AUTHENTICATOR_SQL, + statement -> { + statement.setString(Column.NAME, authenticatorConfigName); + statement.setInt(Column.TENANT_ID, tenantId); + statement.executeUpdate(); + }); + return null; + }); + } catch (TransactionException e) { + throw buildServerException(AuthenticatorMgtError.ERROR_WHILE_DELETING_AUTHENTICATOR, e); + } + } + + private UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticatorByName(String authenticatorConfigName, + int tenantId) throws TransactionException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + AuthenticatorConfigDaoModel configDaoModel = jdbcTemplate.withTransaction(template -> + template.fetchSingleRecord(Query.GET_AUTHENTICATOR_SQL, + (resultSet, rowNumber) -> { + UserDefinedLocalAuthenticatorConfig config = getLocalAuthenticatorConfigBasedOnType( + resultSet.getString(Column.AUTHENTICATION_TYPE)); + config.setName(resultSet.getString(Column.NAME)); + config.setDisplayName(resultSet.getString(Column.DISPLAY_NAME)); + config.setEnabled(resultSet.getString(Column.IS_ENABLED).equals(IS_TRUE_VALUE)); + config.setDefinedByType(DefinedByType.USER); + return new AuthenticatorConfigDaoModel(resultSet.getInt(Column.ID), config); + }, + statement -> { + statement.setString(Column.NAME, authenticatorConfigName); + statement.setInt(Column.TENANT_ID, tenantId); + statement.setString(Column.DEFINED_BY, DefinedByType.USER.toString()); + })); + + if (configDaoModel == null) { + return null; + } + + UserDefinedLocalAuthenticatorConfig config = configDaoModel.getConfig(); + config.setProperties(getAuthenticatorProperties(configDaoModel.getEntryId(), tenantId)); + return config; + } + + private UserDefinedLocalAuthenticatorConfig getLocalAuthenticatorConfigBasedOnType(String authenticationType) { + + if (AuthenticationType.VERIFICATION.toString().equals(authenticationType)) { + return new UserDefinedLocalAuthenticatorConfig(AuthenticationType.VERIFICATION); + } + return new UserDefinedLocalAuthenticatorConfig(AuthenticationType.IDENTIFICATION); + } + + private int getAuthenticatorEntryId(String authenticatorConfigName, int tenantId) + throws AuthenticatorMgtServerException, TransactionException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + int id = jdbcTemplate.withTransaction(template -> + template.fetchSingleRecord(Query.GET_AUTHENTICATOR_ID_SQL, + (resultSet, rowNumber) -> resultSet.getInt(Column.ID), + statement -> { + statement.setString(Column.NAME, authenticatorConfigName); + statement.setInt(Column.TENANT_ID, tenantId); + })); + + if (id != 0) { + return id; + } + throw buildServerException(AuthenticatorMgtError.ERROR_CODE_NO_AUTHENTICATOR_FOUND, + authenticatorConfigName); + } + + private void addAuthenticatorProperty(int authenticatorConfigID, Property[] properties, int tenantId) + throws TransactionException { + + Property prop = properties[0]; + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + jdbcTemplate.withTransaction(template -> + template.executeInsert(Query.ADD_AUTHENTICATOR_PROP_SQL, + statementProp -> { + 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()); + statementProp.setString(Column.IS_SECRET, IS_FALSE_VALUE); + }, null, false)); + } + + private Property[] getAuthenticatorProperties(int authenticatorConfigID, int tenantId) throws TransactionException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + List properties = jdbcTemplate.withTransaction(template -> + template.executeQuery(Query.GET_AUTHENTICATOR_PROP_SQL, + (resultSet, rowNumber) -> { + Property property = new Property(); + property.setName(resultSet.getString(Column.PROPERTY_KEY)); + property.setValue(resultSet.getString(Column.PROPERTY_VALUE)); + property.setConfidential(false); + return property; + }, + statementProp -> { + statementProp.setInt(Column.AUTHENTICATOR_ID, authenticatorConfigID); + statementProp.setInt(Column.TENANT_ID, tenantId); + })); + return properties.toArray(new Property[0]); + } + + /** + * This class represents the user defined local authenticator configuration with entry id from DAO. + */ + private static class AuthenticatorConfigDaoModel { + + private final int entryId; + private final UserDefinedLocalAuthenticatorConfig config; + + private AuthenticatorConfigDaoModel(int entryId, UserDefinedLocalAuthenticatorConfig config) { + this.entryId = entryId; + this.config = config; + } + + public int getEntryId() { + return entryId; + } + + public UserDefinedLocalAuthenticatorConfig getConfig() { + return config; + } + } +} 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..cd182863ec43 --- /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,219 @@ +/* + * 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.lang.StringUtils; +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +import org.wso2.carbon.identity.application.common.dao.AuthenticatorManagementDAO; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +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.application.common.util.AuthenticatorMgtExceptionBuilder; +import org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError; +import org.wso2.carbon.identity.application.common.util.UserDefinedAuthenticatorEndpointConfigManager; +import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; + +import java.util.List; + +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.buildServerException; +import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Authenticator.ACTION_ID_PROPERTY; + +/** + * This class responsible for managing authenticator endpoint configurations for the user defined local + * authenticators. + */ +public class AuthenticatorManagementFacade implements AuthenticatorManagementDAO { + + private final AuthenticatorManagementDAO dao; + private final UserDefinedAuthenticatorEndpointConfigManager endpointConfigManager = + new UserDefinedAuthenticatorEndpointConfigManager(); + + public AuthenticatorManagementFacade(AuthenticatorManagementDAO dao) { + + this.dao = dao; + } + + /** + * Invoke external service to store associated data (endpoint configuration) and create the user defined local + * authenticator to the DB. + * + * @param authenticatorConfig User defined local authenticator configuration. + * @param tenantId Tenant ID. + * @return User defined local authenticator configuration. + * @throws AuthenticatorMgtException If an error occurs while adding the user defined local authenticator. + */ + @Override + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + return jdbcTemplate.withTransaction(template -> { + endpointConfigManager.addEndpointConfigurations(authenticatorConfig, tenantId); + validateAuthenticatorProperties(authenticatorConfig); + return endpointConfigManager.resolveEndpointConfigurations( + dao.addUserDefinedLocalAuthenticator(authenticatorConfig, tenantId), tenantId); + }); + } catch (TransactionException e) { + throw handleAuthenticatorMgtException(AuthenticatorMgtError.ERROR_WHILE_UPDATING_AUTHENTICATOR, e, + authenticatorConfig.getName()); + } + } + + /** + * Invoke external service to update associated data (endpoint configuration) and update the user defined local + * authenticator in DB. + * + * @param existingAuthenticatorConfig Existing user defined local authenticator configuration. + * @param newAuthenticatorConfig New user defined local authenticator configuration. + * @param tenantId Tenant ID. + * @return Updated user defined local authenticator configuration. + * @throws AuthenticatorMgtException If an error occurs while updating the user defined local authenticator. + */ + @Override + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig + existingAuthenticatorConfig, UserDefinedLocalAuthenticatorConfig newAuthenticatorConfig, + int tenantId) throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + return jdbcTemplate.withTransaction(template -> { + endpointConfigManager.updateEndpointConfigurations(newAuthenticatorConfig, existingAuthenticatorConfig, + tenantId); + validateAuthenticatorProperties(newAuthenticatorConfig); + return endpointConfigManager.resolveEndpointConfigurations( + dao.updateUserDefinedLocalAuthenticator(existingAuthenticatorConfig, newAuthenticatorConfig, + tenantId), tenantId); + }); + } catch (TransactionException e) { + throw handleAuthenticatorMgtException(AuthenticatorMgtError.ERROR_WHILE_UPDATING_AUTHENTICATOR, e, + newAuthenticatorConfig.getName()); + } + } + + /** + * Get user defined local authenticator by name and resolving associated data (endpoint configurations) + * by invoking external service. + * + * @param authenticatorConfigName Name of the user defined local authenticator. + * @param tenantId Tenant ID. + * @return User defined local authenticator. + * @throws AuthenticatorMgtException If an error occurs while retrieving the user defined local authenticator. + */ + @Override + public UserDefinedLocalAuthenticatorConfig getUserDefinedLocalAuthenticator( + String authenticatorConfigName, int tenantId) throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + return jdbcTemplate.withTransaction(template -> + endpointConfigManager.resolveEndpointConfigurations(dao.getUserDefinedLocalAuthenticator( + authenticatorConfigName, tenantId), tenantId)); + } catch (TransactionException e) { + throw handleAuthenticatorMgtException(AuthenticatorMgtError.ERROR_WHILE_RETRIEVING_AUTHENTICATOR_BY_NAME, e, + authenticatorConfigName); + } + } + + /** + * Get all user defined local authenticators and resolving associated data (endpoint configurations) + * by invoking external service. + * + * @param tenantId Tenant ID. + * @return List of user defined local authenticators. + * @throws AuthenticatorMgtException If an error occurs while retrieving all user defined local authenticators. + */ + @Override + public List getAllUserDefinedLocalAuthenticators(int tenantId) + throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + return jdbcTemplate.withTransaction(template -> { + List configList = + dao.getAllUserDefinedLocalAuthenticators(tenantId); + // TODO: Utilize a batch operation once issue:https://github.com/wso2/product-is/issues/21783 is done. + for (UserDefinedLocalAuthenticatorConfig config : configList) { + endpointConfigManager.resolveEndpointConfigurations(config, tenantId); + } + return configList; + }); + } catch (TransactionException e) { + throw handleAuthenticatorMgtException( + AuthenticatorMgtError.ERROR_WHILE_ALL_RETRIEVING_AUTHENTICATOR, e, StringUtils.EMPTY); + } + } + + /** + * Invoke external service to delete associated data (endpoint configuration) and delete the user defined local + * authenticator in DB. + * + * @param authenticatorConfigName Name of the user defined local authenticator. + * @param authenticatorConfig User defined local authenticator configuration. + * @param tenantId Tenant ID. + * @throws AuthenticatorMgtException If an error occurs while deleting the user defined local authenticator. + */ + @Override + public void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, UserDefinedLocalAuthenticatorConfig + authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + endpointConfigManager.deleteEndpointConfigurations(authenticatorConfig, tenantId); + dao.deleteUserDefinedLocalAuthenticator(authenticatorConfigName, authenticatorConfig, tenantId); + return null; + }); + } catch (TransactionException e) { + throw handleAuthenticatorMgtException(AuthenticatorMgtError.ERROR_WHILE_DELETING_AUTHENTICATOR, e, + StringUtils.EMPTY); + } + } + + /** + * Handle the authenticator management client exception. + * + * @param throwable Throwable object. + * @throws AuthenticatorMgtClientException If an authenticator management client exception. + */ + private static AuthenticatorMgtException handleAuthenticatorMgtException(AuthenticatorMgtError + authenticatorMgtError, Throwable throwable, String... data) throws AuthenticatorMgtException { + + if (throwable.getCause() instanceof AuthenticatorMgtClientException) { + AuthenticatorMgtClientException error = (AuthenticatorMgtClientException) throwable.getCause(); + throw new AuthenticatorMgtClientException(error.getErrorCode(), error.getMessage(), error.getDescription()); + } + + throw buildServerException(authenticatorMgtError, throwable, data); + } + + private void validateAuthenticatorProperties(UserDefinedLocalAuthenticatorConfig authenticatorConfig) + throws AuthenticatorMgtServerException { + + // User defined local authenticator should have only one property which is the action id. + Property[] properties = authenticatorConfig.getProperties(); + if (!(properties.length == 1 && ACTION_ID_PROPERTY.equals(properties[0].getName()))) { + throw buildServerException(AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError + .ERROR_CODE_HAVING_MULTIPLE_PROP, authenticatorConfig.getName()); + } + } +} 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..e4775e6583e8 --- /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,126 @@ +/* + * 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 java.util.List; + +/** + * Implements caching layer for the AuthenticatorManagementDAO. + */ +public class CacheBackedAuthenticatorMgtDAO implements AuthenticatorManagementDAO { + + private static final Log LOG = LogFactory.getLog(CacheBackedAuthenticatorMgtDAO.class); + private final AuthenticatorCache authenticatorCache; + private final AuthenticatorManagementFacade authenticatorMgtFacade; + + public CacheBackedAuthenticatorMgtDAO(AuthenticatorManagementDAO authenticatorManagementDAO) { + + authenticatorMgtFacade = new AuthenticatorManagementFacade(authenticatorManagementDAO); + authenticatorCache = AuthenticatorCache.getInstance(); + } + + @Override + public UserDefinedLocalAuthenticatorConfig addUserDefinedLocalAuthenticator( + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig createdConfig = authenticatorMgtFacade.addUserDefinedLocalAuthenticator( + authenticatorConfig, tenantId); + + AuthenticatorCacheKey cacheKey = new AuthenticatorCacheKey(authenticatorConfig.getName()); + authenticatorCache.addToCache(cacheKey, new AuthenticatorCacheEntry(createdConfig), tenantId); + if (LOG.isDebugEnabled()) { + LOG.debug(String.format( + "Adding cache entry for newly created authenticator %s.", authenticatorConfig.getName())); + } + return createdConfig; + } + + @Override + public UserDefinedLocalAuthenticatorConfig updateUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig + existingAuthenticatorConfig, UserDefinedLocalAuthenticatorConfig newAuthenticatorConfig, + int tenantId) throws AuthenticatorMgtException { + + AuthenticatorCacheKey cacheKey = new AuthenticatorCacheKey(existingAuthenticatorConfig.getName()); + authenticatorCache.clearCacheEntry(cacheKey, tenantId); + if (LOG.isDebugEnabled()) { + LOG.debug(String.format( + "Delete cache entry of updating authenticator %s.", existingAuthenticatorConfig.getName())); + } + + return authenticatorMgtFacade.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) { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Cache entry found for authenticator %s.", authenticatorConfigName)); + } + return entry.getAuthenticatorConfig(); + } + + if (LOG.isDebugEnabled()) { + LOG.debug(String.format( + "Cache entry not found for authenticator %s. Fetching from DB.", authenticatorConfigName)); + } + UserDefinedLocalAuthenticatorConfig authenticatorConfig = authenticatorMgtFacade + .getUserDefinedLocalAuthenticator(authenticatorConfigName, tenantId); + + authenticatorCache.addToCache(cacheKey, new AuthenticatorCacheEntry(authenticatorConfig), tenantId); + if (LOG.isDebugEnabled()) { + LOG.debug(String.format( + "Entry fetched from DB for authenticator %s. Adding cache entry.", authenticatorConfigName)); + } + return authenticatorConfig; + } + + @Override + public List getAllUserDefinedLocalAuthenticators(int tenantId) + throws AuthenticatorMgtException { + + return authenticatorMgtFacade.getAllUserDefinedLocalAuthenticators(tenantId); + } + + @Override + public void deleteUserDefinedLocalAuthenticator(String authenticatorConfigName, + UserDefinedLocalAuthenticatorConfig authenticatorConfig, int tenantId) throws AuthenticatorMgtException { + + authenticatorCache.clearCacheEntry(new AuthenticatorCacheKey(authenticatorConfigName), tenantId); + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Delete cache entry of deleting authenticator %s.", authenticatorConfigName)); + } + authenticatorMgtFacade.deleteUserDefinedLocalAuthenticator(authenticatorConfigName, authenticatorConfig, + tenantId); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtClientException.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtClientException.java new file mode 100644 index 000000000000..1542f39297fc --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtClientException.java @@ -0,0 +1,30 @@ +/* + * 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.exception; + +/** + * Authenticator configuration management client exception. + */ +public class AuthenticatorMgtClientException extends AuthenticatorMgtException { + + public AuthenticatorMgtClientException(String errorCode, String message, String description) { + + super(message, description, errorCode); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtException.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtException.java new file mode 100644 index 000000000000..1ba49c6214de --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtException.java @@ -0,0 +1,52 @@ +/* + * 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.exception; + +/** + * Authenticator configuration management exception. + */ +public class AuthenticatorMgtException extends Exception { + + private final String errorCode; + private final String description; + + public AuthenticatorMgtException(String message, String description, String errorCode) { + + super(message); + this.errorCode = errorCode; + this.description = description; + } + + public AuthenticatorMgtException(String message, String description, String errorCode, Throwable cause) { + + super(message, cause); + this.errorCode = errorCode; + this.description = description; + } + + public String getErrorCode() { + + return this.errorCode; + } + + public String getDescription() { + + return this.description; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtServerException.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtServerException.java new file mode 100644 index 000000000000..d70c44ab7b83 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtServerException.java @@ -0,0 +1,36 @@ +/* + * 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.exception; + +/** + * Authenticator configuration management server exception. + */ +public class AuthenticatorMgtServerException extends AuthenticatorMgtException { + + public AuthenticatorMgtServerException(String errorCode, String message, String description) { + + super(message, errorCode, description); + } + + public AuthenticatorMgtServerException(String errorCode, String message, String description, + Throwable cause) { + + super(message, description, errorCode, cause); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtServerRuntimeException.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtServerRuntimeException.java new file mode 100644 index 000000000000..3c8d4070f699 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/exception/AuthenticatorMgtServerRuntimeException.java @@ -0,0 +1,48 @@ +/* + * 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.exception; + +/** + * Authenticator configuration management server runtime exception. + */ +public class AuthenticatorMgtServerRuntimeException extends RuntimeException { + + private final String errorCode; + private final String description; + private final Throwable cause; + + public AuthenticatorMgtServerRuntimeException( + String errorCode, String message, String description, Throwable cause) { + + super(message); + this.errorCode = errorCode; + this.description = description; + this.cause = cause; + } + + public String getErrorCode() { + + return this.errorCode; + } + + public String getDescription() { + + return this.description; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/internal/ApplicationCommonServiceComponent.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/internal/ApplicationCommonServiceComponent.java new file mode 100644 index 000000000000..7277f69d2054 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/internal/ApplicationCommonServiceComponent.java @@ -0,0 +1,67 @@ +package org.wso2.carbon.identity.application.common.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.wso2.carbon.identity.action.management.service.ActionManagementService; +import org.wso2.carbon.identity.application.common.ApplicationAuthenticatorService; + +/** + * OSGI service component for the Application Common Service Component. + */ +@Component( + name = "application.common.service.component", + immediate = true +) +public class ApplicationCommonServiceComponent { + + private static final Log LOG = LogFactory.getLog(ApplicationCommonServiceComponent.class); + + @Activate + protected void activate(ComponentContext context) { + + try { + BundleContext bundleCtx = context.getBundleContext(); + bundleCtx.registerService(ApplicationAuthenticatorService.class.getName(), + ApplicationAuthenticatorService.getInstance(), + null); + LOG.debug("Application Authenticator Service is activated."); + } catch (Throwable e) { + LOG.error("Error while initializing Application Authenticator Service component.", e); + } + } + + @Reference( + name = "action.management.service", + service = ActionManagementService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetActionManagementService" + ) + protected void setActionManagementService(ActionManagementService actionManagementService) { + + if (LOG.isDebugEnabled()) { + LOG.debug( + "Registering a reference for ActionManagementService in the ApplicationCommonServiceComponent."); + } + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService(actionManagementService); + } + + protected void unsetActionManagementService(ActionManagementService actionManagementService) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Unregistering the reference for ActionManagementService in the " + + "ApplicationCommonServiceComponent."); + } + if (ApplicationCommonServiceDataHolder.getInstance().getActionManagementService() + .equals(actionManagementService)) { + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService(null); + } + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/internal/ApplicationCommonServiceDataHolder.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/internal/ApplicationCommonServiceDataHolder.java new file mode 100644 index 000000000000..238b81ebcf35 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/internal/ApplicationCommonServiceDataHolder.java @@ -0,0 +1,65 @@ +package org.wso2.carbon.identity.application.common.internal; + +import org.wso2.carbon.identity.action.management.service.ActionManagementService; +import org.wso2.carbon.identity.application.common.ApplicationAuthenticatorService; + +/** + * The data holder for the Application Common Service Component. + */ +public class ApplicationCommonServiceDataHolder { + + private static final ApplicationCommonServiceDataHolder INSTANCE = new ApplicationCommonServiceDataHolder(); + + private ActionManagementService actionManagementService; + private ApplicationAuthenticatorService applicationAuthenticatorService; + + /** + * Get the instance of the ApplicationCommonServiceDataHolder. + * + * @return ApplicationCommonServiceDataHolder instance. + */ + public static ApplicationCommonServiceDataHolder getInstance() { + + return INSTANCE; + } + + /** + * Get the ActionManagementService. + * + * @return ActionManagementService instance. + */ + public ActionManagementService getActionManagementService() { + + return actionManagementService; + } + + /** + * Set the ActionManagementService. + * + * @param actionManagementService ActionManagementService instance. + */ + public void setActionManagementService(ActionManagementService actionManagementService) { + + this.actionManagementService = actionManagementService; + } + + /** + * Get the ApplicationAuthenticatorService. + * + * @return ApplicationAuthenticatorService instance. + */ + public ApplicationAuthenticatorService getApplicationAuthenticatorService() { + + return applicationAuthenticatorService; + } + + /** + * Set the ApplicationAuthenticatorService. + * + * @param applicationAuthenticatorService ApplicationAuthenticatorService instance. + */ + public void setApplicationAuthenticatorService(ApplicationAuthenticatorService applicationAuthenticatorService) { + + this.applicationAuthenticatorService = applicationAuthenticatorService; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedFederatedAuthenticatorConfig.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedFederatedAuthenticatorConfig.java index c7fc749a3718..f91d7d1714a6 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedFederatedAuthenticatorConfig.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedFederatedAuthenticatorConfig.java @@ -20,14 +20,14 @@ import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType; +import static org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.TAG_CUSTOM; + /** * The user defined federated authenticator configuration model. */ public class UserDefinedFederatedAuthenticatorConfig extends FederatedAuthenticatorConfig { - private static final String TAG_CUSTOM = "CUSTOM"; - - protected UserDefinedAuthenticatorEndpointConfig endpointConfig; + private UserDefinedAuthenticatorEndpointConfig endpointConfig; public UserDefinedFederatedAuthenticatorConfig() { @@ -36,7 +36,7 @@ public UserDefinedFederatedAuthenticatorConfig() { } /** - * Get the endpoint configurations of the User defined federated authenticator config. + * Get the endpoint configurations of the user defined federated authenticator config. * * @return UserDefinedAuthenticatorEndpointConfig */ @@ -46,9 +46,9 @@ public UserDefinedAuthenticatorEndpointConfig getEndpointConfig() { } /** - * Set the endpoint configurations of the User defined federated authenticator config. + * Set the endpoint configurations of the user defined federated authenticator config. * - * @param endpointConfig The endpoint config of the User defined federated authenticator config. + * @param endpointConfig The endpoint config of the user defined federated authenticator config. */ public void setEndpointConfig(UserDefinedAuthenticatorEndpointConfig endpointConfig) { diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedLocalAuthenticatorConfig.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedLocalAuthenticatorConfig.java index fab5a37a69bd..75a9a3114eda 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedLocalAuthenticatorConfig.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/UserDefinedLocalAuthenticatorConfig.java @@ -21,18 +21,20 @@ import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.AuthenticationType; import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType; +import static org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.TAG_2FA; +import static org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.TAG_CUSTOM; + /** * The user defined local authenticator configuration model. */ public class UserDefinedLocalAuthenticatorConfig extends LocalAuthenticatorConfig { - private static final String TAG_2FA = "2FA"; - private static final String TAG_CUSTOM = "CUSTOM"; - - protected UserDefinedAuthenticatorEndpointConfig endpointConfig; + private AuthenticationType authenticationType; + private UserDefinedAuthenticatorEndpointConfig endpointConfig; public UserDefinedLocalAuthenticatorConfig(AuthenticationType type) { + authenticationType = type; definedByType = DefinedByType.USER; if (AuthenticationType.VERIFICATION == type) { setTags(new String[]{TAG_CUSTOM, TAG_2FA}); @@ -42,7 +44,7 @@ public UserDefinedLocalAuthenticatorConfig(AuthenticationType type) { } /** - * Get the endpoint configurations of the User defined local authenticator config. + * Get the endpoint configurations of the user defined local authenticator config. * * @return UserDefinedAuthenticatorEndpointConfig */ @@ -52,12 +54,32 @@ public UserDefinedAuthenticatorEndpointConfig getEndpointConfig() { } /** - * Set the endpoint configurations of the User defined local authenticator config. + * Set the endpoint configurations of the user defined local authenticator config. * - * @param endpointConfig The endpoint config of the User defined local authenticator config. + * @param endpointConfig The endpoint config of the user defined local authenticator config. */ public void setEndpointConfig(UserDefinedAuthenticatorEndpointConfig endpointConfig) { this.endpointConfig = endpointConfig; } + + /** + * Get the authentication type of the user defined local authenticator config. + * + * @return AuthenticationType. + */ + public AuthenticationType getAuthenticationType() { + + return authenticationType; + } + + /** + * Set the authentication type of the user defined local authenticator config. + * + * @param authenticationType The authentication type of the user defined local authenticator config. + */ + public void setAuthenticationType(AuthenticationType authenticationType) { + + this.authenticationType = authenticationType; + } } diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/AuthenticatorMgtExceptionBuilder.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/AuthenticatorMgtExceptionBuilder.java new file mode 100644 index 000000000000..eb32b47d8d22 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/AuthenticatorMgtExceptionBuilder.java @@ -0,0 +1,148 @@ +/* + * 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.util; + +import org.apache.commons.lang.ArrayUtils; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtServerException; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtServerRuntimeException; + +/** + * Utility class for building authenticator management exceptions. + */ +public class AuthenticatorMgtExceptionBuilder { + + private AuthenticatorMgtExceptionBuilder() { + + } + + public static AuthenticatorMgtClientException buildClientException(AuthenticatorMgtError error, String... data) { + + String description = error.getDescription(); + if (ArrayUtils.isNotEmpty(data)) { + description = String.format(description, data); + } + + return new AuthenticatorMgtClientException(error.getCode(), error.getMessage(), description); + } + + public static AuthenticatorMgtServerException buildServerException(AuthenticatorMgtError error, String... data) { + + String description = error.getDescription(); + if (ArrayUtils.isNotEmpty(data)) { + description = String.format(description, data); + } + + return new AuthenticatorMgtServerException(error.getCode(), error.getMessage(), description); + } + + public static AuthenticatorMgtServerException buildServerException(AuthenticatorMgtError error, Throwable e, + String... data) { + + String description = error.getDescription(); + if (ArrayUtils.isNotEmpty(data)) { + description = String.format(description, data); + } + + return new AuthenticatorMgtServerException(error.getCode(), error.getMessage(), description, e); + } + + public static AuthenticatorMgtServerRuntimeException buildRuntimeServerException(AuthenticatorMgtError error, + Throwable e, String... data) { + + String description = error.getDescription(); + if (ArrayUtils.isNotEmpty(data)) { + description = String.format(description, data); + } + + return new AuthenticatorMgtServerRuntimeException(error.getCode(), error.getMessage(), description, e); + } + + /** + * Enum class to represent the rule metadata errors. + */ + public enum AuthenticatorMgtError { + + // Client errors. + ERROR_NOT_FOUND_AUTHENTICATOR("60001", "No Authenticator found.", + "No Authenticator found by given authenticator name: %s."), + ERROR_OPERATION_ALLOWED_FOR_SYSTEM_AUTHENTICATOR("60002", "No operations allowed on system " + + "authenticators.", "Do not allow to perform any operation on system defined authenticator: %s."), + ERROR_AUTHENTICATOR_ALREADY_EXIST("60003", "The authenticator already exists.", + "The authenticator already exists for the given name: %s."), + ERROR_INVALID_AUTHENTICATOR_NAME("60004", "Authenticator name is invalid.", + "The provided authenticator name %s is not in the expected format %s."), + ERROR_BLANK_FIELD_VALUE("60004", "Invalid empty or blank value.", + "Value for %s should not be empty or blank."), + + // Server errors. + ERROR_WHILE_ADDING_AUTHENTICATOR("65001", "Error while adding authenticator.", + "Error while persisting authenticator to the system."), + ERROR_WHILE_UPDATING_AUTHENTICATOR("65002", "Error while updating authenticator.", + "Error while updating authenticator in the system."), + ERROR_WHILE_RETRIEVING_AUTHENTICATOR_BY_NAME("65003", "Error while retrieving authenticator.", + "Error while retrieving authenticator in the system."), + ERROR_WHILE_ALL_RETRIEVING_AUTHENTICATOR("65004", "Error while all retrieving authenticator.", + "Error while retrieving all authenticators in the system."), + ERROR_WHILE_DELETING_AUTHENTICATOR("65005", "Error while deleting authenticator.", + "Error while deleting authenticator in the system."), + ERROR_CODE_INVALID_DEFINED_BY_AUTH_PROVIDED("65006", "Error while adding local authenticator.", + "Only system defined authenticators are allowed to add via this method."), + ERROR_CODE_NO_AUTHENTICATOR_FOUND("65007", "No authenticator found.", + "No authenticator found by given authenticator name: %s."), + ERROR_CODE_NO_ACTION_ID_FOUND("65008", "No action id found.", + "No action id found for the authenticator: %s."), + ERROR_CODE_ADDING_ENDPOINT_CONFIG("65009", "Error while adding endpoint configurations.", + "Error while adding endpoint configurations for the user defined local authenticator %s."), + ERROR_CODE_UPDATING_ENDPOINT_CONFIG("65010", "Error while updating endpoint configurations.", + "Error while updating endpoint configurations for the user defined local authenticator %s."), + ERROR_CODE_RETRIEVING_ENDPOINT_CONFIG("65011", "Error while resolving endpoint configurations.", + "Error while retrieving endpoint configurations for the user defined local authenticator %s."), + ERROR_CODE_DELETING_ENDPOINT_CONFIG("65012", "Error while managing endpoint configurations.", + "Error while managing endpoint configurations for the user defined local authenticator %s."), + ERROR_CODE_HAVING_MULTIPLE_PROP("65013", "Multiple properties found", "Only actionId " + + "property is allowed for authenticator: %s."); + + private final String code; + private final String message; + private final String description; + + AuthenticatorMgtError(String code, String message, String description) { + + this.code = code; + this.message = message; + this.description = description; + } + + public String getCode() { + + return code; + } + + public String getMessage() { + + return message; + } + + public String getDescription() { + + return description; + } + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/IdentityApplicationConstants.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/IdentityApplicationConstants.java index 1c748599ab6c..655e4e0674c3 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/IdentityApplicationConstants.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/IdentityApplicationConstants.java @@ -166,6 +166,9 @@ private ConfigElements() { */ public static class Authenticator { + public static final String ACTION_ID_PROPERTY = "actionId"; + public static final String DISPLAY_NAME = "displayName"; + /** * OpenId authenticator constants. */ diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/UserDefinedAuthenticatorEndpointConfigManager.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/UserDefinedAuthenticatorEndpointConfigManager.java new file mode 100644 index 000000000000..50d304aa53b6 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/UserDefinedAuthenticatorEndpointConfigManager.java @@ -0,0 +1,206 @@ +/* + * 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.util; + +import org.wso2.carbon.identity.action.management.exception.ActionMgtClientException; +import org.wso2.carbon.identity.action.management.exception.ActionMgtException; +import org.wso2.carbon.identity.action.management.model.Action; +import org.wso2.carbon.identity.action.management.model.EndpointConfig; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +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.internal.ApplicationCommonServiceDataHolder; +import org.wso2.carbon.identity.application.common.model.Property; +import org.wso2.carbon.identity.application.common.model.UserDefinedAuthenticatorEndpointConfig; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.buildServerException; +import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Authenticator.ACTION_ID_PROPERTY; + +/** + * This class responsible for managing authenticator endpoint configurations for the user defined Local + * authenticators. + */ +public class UserDefinedAuthenticatorEndpointConfigManager { + + /** + * Create a new action for given endpoint configurations of the user defined authenticator. + * + * @param config The Local application authenticator configuration. + * @param tenantId The id of Tenant domain. + * @throws AuthenticatorMgtException If an error occurs while adding the action. + */ + public void addEndpointConfigurations(UserDefinedLocalAuthenticatorConfig config, int tenantId) + throws AuthenticatorMgtException { + + try { + Action action = ApplicationCommonServiceDataHolder.getInstance().getActionManagementService() + .addAction(Action.ActionTypes.AUTHENTICATION.getPathParam(), + buildActionToCreate(config.getName(), config.getEndpointConfig().getEndpointConfig()), + IdentityTenantUtil.getTenantDomain(tenantId)); + Property endpointProperty = new Property(); + endpointProperty.setName(ACTION_ID_PROPERTY); + endpointProperty.setValue(action.getId()); + config.setProperties(new Property[]{endpointProperty}); + } catch (ActionMgtException e) { + throw handleActionMgtException(AuthenticatorMgtError.ERROR_CODE_ADDING_ENDPOINT_CONFIG, + e, config.getName()); + } + } + + /** + * Updated associated action for given updated endpoint configurations of the user defined authenticator. + * + * @param newConfig The Local application authenticator configuration to be updated. + * @param oldConfig The current Local application authenticator configuration. + * @param tenantId The id of Tenant domain. + * @throws AuthenticatorMgtException If an error occurs while updating associated action. + */ + public void updateEndpointConfigurations(UserDefinedLocalAuthenticatorConfig newConfig, + UserDefinedLocalAuthenticatorConfig oldConfig, int tenantId) + throws AuthenticatorMgtException { + + String actionId = getActionIdFromProperty(oldConfig.getProperties(), oldConfig.getName()); + try { + ApplicationCommonServiceDataHolder.getInstance().getActionManagementService() + .updateAction(Action.ActionTypes.AUTHENTICATION.getPathParam(), + actionId, + buildActionToUpdate(newConfig.getEndpointConfig().getEndpointConfig()), + IdentityTenantUtil.getTenantDomain(tenantId)); + newConfig.setProperties(oldConfig.getProperties()); + } catch (ActionMgtException e) { + throw handleActionMgtException(AuthenticatorMgtError.ERROR_CODE_UPDATING_ENDPOINT_CONFIG, e, + actionId, oldConfig.getName()); + } + } + + /** + * Retrieve associated action of the user defined authenticator. + * + * @param config The Local application authenticator configuration. + * @param tenantId The id of Tenant domain. + * @return Local authenticator with endpoint configurations resolved. + * @throws AuthenticatorMgtException If an error occurs retrieving updating associated action. + */ + public UserDefinedLocalAuthenticatorConfig resolveEndpointConfigurations(UserDefinedLocalAuthenticatorConfig config, + int tenantId) throws AuthenticatorMgtException { + + if (config == null) { + return null; + } + String actionId = getActionIdFromProperty(config.getProperties(), config.getName()); + try { + Action action = ApplicationCommonServiceDataHolder.getInstance().getActionManagementService() + .getActionByActionId(Action.ActionTypes.AUTHENTICATION.getPathParam(), + actionId, + IdentityTenantUtil.getTenantDomain(tenantId)); + + config.setEndpointConfig(buildUserDefinedAuthenticatorEndpointConfig(action.getEndpoint())); + return config; + } catch (ActionMgtException e) { + throw handleActionMgtException(AuthenticatorMgtError.ERROR_CODE_RETRIEVING_ENDPOINT_CONFIG, e, + actionId, config.getName()); + } + } + + private UserDefinedAuthenticatorEndpointConfig buildUserDefinedAuthenticatorEndpointConfig( + EndpointConfig endpointConfig) { + + UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder endpointConfigBuilder = + new UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder(); + endpointConfigBuilder.uri(endpointConfig.getUri()); + endpointConfigBuilder.authenticationType(endpointConfig.getAuthentication().getType().getName()); + Map propMap = new HashMap<>(); + endpointConfig.getAuthentication().getProperties() + .forEach(prop -> propMap.put(prop.getName(), prop.getValue())); + endpointConfigBuilder.authenticationProperties(propMap); + return endpointConfigBuilder.build(); + } + + /** + * Delete associated action of the user defined authenticator. + * + * @param config The Local application authenticator configuration. + * @param tenantId The id of Tenant domain. + * @throws AuthenticatorMgtException If an error occurs while deleting associated action. + */ + public void deleteEndpointConfigurations(UserDefinedLocalAuthenticatorConfig config, int tenantId) throws + AuthenticatorMgtException { + + String actionId = getActionIdFromProperty(config.getProperties(), config.getName()); + try { + ApplicationCommonServiceDataHolder.getInstance().getActionManagementService() + .deleteAction(Action.ActionTypes.AUTHENTICATION.getPathParam(), + actionId, + IdentityTenantUtil.getTenantDomain(tenantId)); + } catch (ActionMgtException e) { + throw handleActionMgtException(AuthenticatorMgtError.ERROR_CODE_DELETING_ENDPOINT_CONFIG, e, + actionId, config.getName()); + } + } + + private Action buildActionToCreate(String authenticatorName, EndpointConfig endpointConfig) { + + Action.ActionRequestBuilder actionRequestBuilder = new Action.ActionRequestBuilder(); + actionRequestBuilder.name(authenticatorName); + actionRequestBuilder.description(String.format("This is the action associated to the user defined Local" + + "authenticator %s.", authenticatorName)); + actionRequestBuilder.endpoint(endpointConfig); + + return actionRequestBuilder.build(); + } + + private Action buildActionToUpdate(EndpointConfig endpointConfig) { + + Action.ActionRequestBuilder actionRequestBuilder = new Action.ActionRequestBuilder(); + actionRequestBuilder.endpoint(endpointConfig); + + return actionRequestBuilder.build(); + } + + private String getActionIdFromProperty(Property[] properties, String authenticatorName) + throws AuthenticatorMgtServerException { + + return Arrays.stream(properties) + .filter(property -> ACTION_ID_PROPERTY.equals(property.getName())) + .map(Property::getValue) + .findFirst() + .orElseThrow(() -> buildServerException(AuthenticatorMgtError.ERROR_CODE_NO_ACTION_ID_FOUND, + authenticatorName)); + } + + private static AuthenticatorMgtException handleActionMgtException(AuthenticatorMgtError authenticatorMgtError, + Throwable actionException, String... data) + throws AuthenticatorMgtException { + + if (actionException instanceof ActionMgtClientException) { + ActionMgtClientException error = (ActionMgtClientException) actionException; + throw new AuthenticatorMgtClientException( + authenticatorMgtError.getCode(), error.getMessage(), error.getDescription()); + } + + throw buildServerException(authenticatorMgtError, data); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/UserDefinedLocalAuthenticatorValidator.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/UserDefinedLocalAuthenticatorValidator.java new file mode 100644 index 000000000000..836607835390 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/util/UserDefinedLocalAuthenticatorValidator.java @@ -0,0 +1,65 @@ +/* + * 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.util; + +import org.apache.commons.lang.StringUtils; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +import org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError; + +import java.util.regex.Pattern; + +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.buildClientException; + +/** + * User Defined Local Authenticator Validator class. + */ +public class UserDefinedLocalAuthenticatorValidator { + + private static final String AUTHENTICATOR_NAME_REGEX = "^[a-zA-Z0-9][a-zA-Z0-9-_]*$"; + private final Pattern authenticatorNameRegexPattern = Pattern.compile(AUTHENTICATOR_NAME_REGEX); + + /** + * Validate whether required fields exist. + * + * @param fieldName Field name. + * @param fieldValue Field value. + * @throws AuthenticatorMgtClientException if the provided field is empty. + */ + public void validateForBlank(String fieldName, String fieldValue) throws AuthenticatorMgtClientException { + + if (StringUtils.isBlank(fieldValue)) { + throw buildClientException(AuthenticatorMgtError.ERROR_BLANK_FIELD_VALUE, fieldName); + } + } + + /** + * Validate the user defined local authenticator name. + * + * @param name The authenticator name. + * @throws AuthenticatorMgtClientException if the authenticator name is not valid. + */ + public void validateAuthenticatorName(String name) throws AuthenticatorMgtClientException { + + boolean isValidName = authenticatorNameRegexPattern.matcher(name).matches(); + if (!isValidName) { + throw buildClientException(AuthenticatorMgtError.ERROR_INVALID_AUTHENTICATOR_NAME, + name, AUTHENTICATOR_NAME_REGEX); + } + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/ApplicationAuthenticatorServiceTest.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/ApplicationAuthenticatorServiceTest.java new file mode 100644 index 000000000000..f75199d6e85e --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/ApplicationAuthenticatorServiceTest.java @@ -0,0 +1,384 @@ +/* + * 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.model.test; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.action.management.exception.ActionMgtClientException; +import org.wso2.carbon.identity.action.management.exception.ActionMgtServerException; +import org.wso2.carbon.identity.action.management.model.Action; +import org.wso2.carbon.identity.action.management.model.EndpointConfig; +import org.wso2.carbon.identity.action.management.service.ActionManagementService; +import org.wso2.carbon.identity.application.common.ApplicationAuthenticatorService; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtClientException; +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.exception.AuthenticatorMgtServerRuntimeException; +import org.wso2.carbon.identity.application.common.internal.ApplicationCommonServiceDataHolder; +import org.wso2.carbon.identity.application.common.model.LocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.test.util.ActionMgtTestUtil; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.AuthenticationType; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType; +import org.wso2.carbon.identity.common.testng.WithAxisConfiguration; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.common.testng.WithH2Database; +import org.wso2.carbon.identity.common.testng.WithRealmService; +import org.wso2.carbon.identity.common.testng.WithRegistry; +import org.wso2.carbon.identity.core.internal.IdentityCoreServiceDataHolder; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.wso2.carbon.identity.application.common.model.test.util.ActionMgtTestUtil.mockActionService; +import static org.wso2.carbon.identity.application.common.model.test.util.UserDefinedLocalAuthenticatorDataUtil.createSystemDefinedAuthenticatorConfig; +import static org.wso2.carbon.identity.application.common.model.test.util.UserDefinedLocalAuthenticatorDataUtil.createUserDefinedAuthenticatorConfig; +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError.ERROR_CODE_INVALID_DEFINED_BY_AUTH_PROVIDED; + +/** + * This class is a test suite for the ApplicationAuthenticatorServiceTest class. + * It contains unit tests to verify the functionality of the methods + * in the ApplicationAuthenticatorServiceTest class. + */ +@WithAxisConfiguration +@WithCarbonHome +@WithH2Database(files = {"dbscripts/h2.sql"}) +@WithRegistry +@WithRealmService(injectToSingletons = {IdentityCoreServiceDataHolder.class}) +public class ApplicationAuthenticatorServiceTest { + + private String tenantDomain; + + private UserDefinedLocalAuthenticatorConfig authenticatorConfig1; + private UserDefinedLocalAuthenticatorConfig authenticatorConfig2; + private UserDefinedLocalAuthenticatorConfig authenticatorConfigForException; + private UserDefinedLocalAuthenticatorConfig nonExistAuthenticatorConfig; + private LocalAuthenticatorConfig systemAuthenticatorConfig; + + private ActionManagementService actionManagementService; + private static Action action; + private static EndpointConfig endpointConfig; + private static EndpointConfig endpointConfigToBeUpdated; + + private static final String AUTHENTICATOR1_NAME = "auth1"; + private static final String AUTHENTICATOR2_NAME = "auth2"; + private static final String AUTHENTICATOR_CONFIG_FOR_EXCEPTION_NAME = "exception_auth"; + private static final String NON_EXIST_AUTHENTICATOR_NAME = "non_exist_auth"; + private static final String SYSTEM_AUTHENTICATOR_NAME = "system_auth"; + + @BeforeClass + public void setUpClass() throws Exception { + + tenantDomain = "carbon.super"; + systemAuthenticatorConfig = createSystemDefinedAuthenticatorConfig(SYSTEM_AUTHENTICATOR_NAME); + authenticatorConfig1 = createUserDefinedAuthenticatorConfig(AUTHENTICATOR1_NAME, + AuthenticationType.IDENTIFICATION); + authenticatorConfig2 = createUserDefinedAuthenticatorConfig(AUTHENTICATOR2_NAME, + AuthenticationType.VERIFICATION); + nonExistAuthenticatorConfig = createUserDefinedAuthenticatorConfig(NON_EXIST_AUTHENTICATOR_NAME, + AuthenticationType.IDENTIFICATION); + authenticatorConfigForException = createUserDefinedAuthenticatorConfig(AUTHENTICATOR_CONFIG_FOR_EXCEPTION_NAME, + AuthenticationType.IDENTIFICATION); + + endpointConfig = ActionMgtTestUtil.createEndpointConfig("http://localhost", "admin", "admin"); + endpointConfigToBeUpdated = ActionMgtTestUtil.createEndpointConfig( + "http://localhost1", "admin1", "admin1"); + action = ActionMgtTestUtil.createAction(endpointConfig); + actionManagementService = mockActionService(action); + + ApplicationCommonServiceDataHolder.getInstance().setApplicationAuthenticatorService( + ApplicationAuthenticatorService.getInstance()); + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService(actionManagementService); + } + + @AfterClass + public void tearDownClass() throws AuthenticatorMgtException { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .deleteUserDefinedLocalAuthenticator(AUTHENTICATOR1_NAME, tenantDomain); + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .deleteUserDefinedLocalAuthenticator(AUTHENTICATOR2_NAME, tenantDomain); + } + + @AfterMethod + public void tearDown() { + + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService(actionManagementService); + } + + @DataProvider(name = "authenticatorConfigForCreation") + public Object[][] authenticatorConfigForCreation() { + + return new Object[][]{ + {authenticatorConfig1}, + {authenticatorConfig2} + }; + } + + @Test(priority = 1, dataProvider = "authenticatorConfigForCreation") + public void testCreateUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig config) + throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig createdAuthenticator = ApplicationCommonServiceDataHolder.getInstance() + .getApplicationAuthenticatorService().addUserDefinedLocalAuthenticator(config, tenantDomain); + + Assert.assertEquals(createdAuthenticator.getName(), config.getName()); + Assert.assertEquals(createdAuthenticator.getDisplayName(), config.getDisplayName()); + Assert.assertEquals(createdAuthenticator.isEnabled(), config.isEnabled()); + Assert.assertEquals(createdAuthenticator.getDefinedByType(), DefinedByType.USER); + if (AuthenticationType.VERIFICATION == config.getAuthenticationType()) { + Assert.assertTrue(Arrays.asList(createdAuthenticator.getTags()).contains("2FA"), + "Tag list does not contain 2FA tag for verification authentication type."); + } + Assert.assertEquals(createdAuthenticator.getProperties().length, config.getProperties().length); + } + + @Test(priority = 2, dataProvider = "authenticatorConfigForCreation", expectedExceptions = + AuthenticatorMgtException.class, expectedExceptionsMessageRegExp = "The authenticator already exists.") + public void testCreateUserDefinedLocalAuthenticatorWithExistingAuthenticator( + UserDefinedLocalAuthenticatorConfig config) throws AuthenticatorMgtException { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator(config, tenantDomain); + } + + @Test(priority = 3, expectedExceptions = AuthenticatorMgtException.class, + expectedExceptionsMessageRegExp = "Invalid empty or blank value.") + public void testCreateUserDefinedLocalAuthenticatorWithBlankDisplayName() throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig config = createUserDefinedAuthenticatorConfig("withBlankDisplayName", + AuthenticationType.IDENTIFICATION); + config.setDisplayName(""); + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator(config, tenantDomain); + } + + @Test(priority = 4, expectedExceptions = AuthenticatorMgtException.class, + expectedExceptionsMessageRegExp = "Authenticator name is invalid.") + public void testCreateUserDefinedLocalAuthenticatorWithInvalidName() throws AuthenticatorMgtException { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator(createUserDefinedAuthenticatorConfig("323#2@dwd", + AuthenticationType.IDENTIFICATION), tenantDomain); + } + + @Test(priority = 5) + public void testAddIdPActionServerException() throws Exception { + + ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); + when(actionManagementServiceForException.addAction(anyString(), any(), any())) + .thenThrow(ActionMgtServerException.class); + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService( + actionManagementServiceForException); + + assertThrows(AuthenticatorMgtServerException.class, () -> + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator(authenticatorConfigForException, tenantDomain)); + } + + @Test(priority = 6) + public void testAddIdPActionClientException() throws Exception { + + ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); + when(actionManagementServiceForException.addAction(anyString(), any(), any())) + .thenThrow(ActionMgtClientException.class); + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService( + actionManagementServiceForException); + + assertThrows(AuthenticatorMgtClientException.class, () -> + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator(authenticatorConfigForException, tenantDomain)); + } + + @Test(priority = 7) + public void testAddLocalAuthenticator() { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addLocalAuthenticator(systemAuthenticatorConfig); + Assert.assertNotNull(ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .getLocalAuthenticatorByName(SYSTEM_AUTHENTICATOR_NAME)); + } + + @Test(priority = 8) + public void testAddLocalAuthenticatorWithRuntimeError() { + + AuthenticatorMgtServerRuntimeException exception = assertThrows(AuthenticatorMgtServerRuntimeException.class, + () -> ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addLocalAuthenticator(authenticatorConfig1)); + Assert.assertEquals(exception.getErrorCode(), ERROR_CODE_INVALID_DEFINED_BY_AUTH_PROVIDED.getCode()); + + } + + @Test(priority = 9) + public void testGetAllUserDefinedLocalAuthenticators() throws Exception { + + List authenticatorsList = ApplicationCommonServiceDataHolder.getInstance() + .getApplicationAuthenticatorService().getAllUserDefinedLocalAuthenticators(tenantDomain); + Assert.assertEquals(authenticatorsList.size(), 2); + } + + @DataProvider(name = "authenticatorConfigToModify") + public Object[][] authenticatorConfigToModify() { + + authenticatorConfig1.setDisplayName("Updated Display Name"); + + authenticatorConfig2.setEnabled(false); + authenticatorConfig2.setDefinedByType(DefinedByType.SYSTEM); + + return new Object[][]{ + {authenticatorConfig1}, + {authenticatorConfig2} + }; + } + + @Test(priority = 10) + public void testGetUserDefinedAuthenticator() throws Exception { + + UserDefinedLocalAuthenticatorConfig authenticator = ApplicationCommonServiceDataHolder.getInstance() + .getApplicationAuthenticatorService().getUserDefinedLocalAuthenticator( + authenticatorConfig1.getName(), tenantDomain); + Assert.assertNotNull(authenticator); + } + + @Test(priority = 11) + public void testGetUserDefinedAuthenticatorWithActionException() throws Exception { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .addUserDefinedLocalAuthenticator(authenticatorConfigForException, tenantDomain); + ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); + when(actionManagementServiceForException.addAction(anyString(), any(), any())).thenReturn(action); + when(actionManagementServiceForException.getActionByActionId(anyString(), any(), any())) + .thenThrow(ActionMgtServerException.class); + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService( + actionManagementServiceForException); + } + + @Test(priority = 12, dataProvider = "authenticatorConfigToModify") + public void testUpdateUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig config) + throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig updatedAuthenticator = ApplicationCommonServiceDataHolder.getInstance() + .getApplicationAuthenticatorService().updateUserDefinedLocalAuthenticator(config, tenantDomain); + + Assert.assertEquals(updatedAuthenticator.getName(), config.getName()); + Assert.assertEquals(updatedAuthenticator.getDisplayName(), config.getDisplayName()); + Assert.assertEquals(updatedAuthenticator.isEnabled(), config.isEnabled()); + Assert.assertEquals(updatedAuthenticator.getDefinedByType(), DefinedByType.USER); + Assert.assertEquals(updatedAuthenticator.getProperties().length, config.getProperties().length); + } + + @Test(priority = 13, expectedExceptions = AuthenticatorMgtException.class, + expectedExceptionsMessageRegExp = "No Authenticator found.") + public void testUpdateUserDefinedLocalAuthenticatorWithNonExistingAuthenticator() throws AuthenticatorMgtException { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .updateUserDefinedLocalAuthenticator(nonExistAuthenticatorConfig, tenantDomain); + } + + @Test(priority = 14) + public void testUpdateIdPActionException() throws Exception { + + ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); + when(actionManagementServiceForException.updateAction(any(), any(), any(), any())) + .thenThrow(ActionMgtServerException.class); + when(actionManagementServiceForException.getActionByActionId(anyString(), any(), any())).thenReturn(action); + ApplicationCommonServiceDataHolder.getInstance().setActionManagementService( + actionManagementServiceForException); + + assertThrows(AuthenticatorMgtServerException.class, () -> ApplicationCommonServiceDataHolder.getInstance() + .getApplicationAuthenticatorService().updateUserDefinedLocalAuthenticator( + authenticatorConfigForException, tenantDomain)); + } + + @DataProvider(name = "authenticatorConfigToRetrieve") + public Object[][] authenticatorConfigToRetrieve() { + + return new Object[][]{ + {authenticatorConfig1, authenticatorConfig1, AuthenticationType.IDENTIFICATION.toString()}, + {authenticatorConfig2, authenticatorConfig2, AuthenticationType.VERIFICATION.toString()}, + {nonExistAuthenticatorConfig, null, null} + }; + } + + @Test(priority = 15, dataProvider = "authenticatorConfigToRetrieve") + public void testGetUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig configToBeRetrieved, + UserDefinedLocalAuthenticatorConfig expectedConfig, String type) throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig retrievedConfig = ApplicationCommonServiceDataHolder.getInstance() + .getApplicationAuthenticatorService().getUserDefinedLocalAuthenticator( + configToBeRetrieved.getName(), tenantDomain); + Assert.assertEquals(retrievedConfig, expectedConfig); + if (expectedConfig != null) { + Assert.assertEquals(retrievedConfig.getDisplayName(), expectedConfig.getDisplayName()); + Assert.assertEquals(retrievedConfig.isEnabled(), expectedConfig.isEnabled()); + Assert.assertEquals(retrievedConfig.getDefinedByType(), DefinedByType.USER); + if (AuthenticationType.VERIFICATION.toString().equals(type)) { + Assert.assertTrue(Arrays.asList(retrievedConfig.getTags()).contains("2FA"), + "Tag list does not contain 2FA tag for verification authentication type."); + } + Assert.assertEquals(retrievedConfig.getProperties().length, expectedConfig.getProperties().length); + } + } + + @Test(priority = 16) + public void testDeleteUserDefinedLocalAuthenticatorWithActionException() throws Exception { + + ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); + doThrow(ActionMgtServerException.class) + .when(actionManagementServiceForException).deleteAction(any(), any(), any()); + when(actionManagementServiceForException.getActionByActionId(anyString(), any(), any())).thenReturn(action); + ApplicationCommonServiceDataHolder.getInstance() + .setActionManagementService(actionManagementServiceForException); + + assertThrows(AuthenticatorMgtServerException.class, () -> ApplicationCommonServiceDataHolder.getInstance(). + getApplicationAuthenticatorService().deleteUserDefinedLocalAuthenticator( + authenticatorConfigForException.getName(), tenantDomain)); + Assert.assertNotNull(ApplicationCommonServiceDataHolder.getInstance(). + getApplicationAuthenticatorService().getUserDefinedLocalAuthenticator( + authenticatorConfigForException.getName(), tenantDomain)); + } + + @Test(priority = 17, dataProvider = "authenticatorConfigToModify") + public void testDeleteUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig config) + throws AuthenticatorMgtException { + + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .deleteUserDefinedLocalAuthenticator(config.getName(), tenantDomain); + Assert.assertNull(ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .getLocalAuthenticatorByName(config.getName())); + } + + @Test(priority = 18) + public void testDeleteUserDefinedLocalAuthenticatorWithNonExistingAuthenticator() throws AuthenticatorMgtException { + + // Assert that no exception is thrown when trying to delete a non-existing authenticator. + ApplicationCommonServiceDataHolder.getInstance().getApplicationAuthenticatorService() + .deleteUserDefinedLocalAuthenticator(nonExistAuthenticatorConfig.getName(), tenantDomain); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/UserDefinedAuthenticatorTest.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/UserDefinedAuthenticatorTest.java index 61c115d3dc94..97fcc362417a 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/UserDefinedAuthenticatorTest.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/UserDefinedAuthenticatorTest.java @@ -29,6 +29,8 @@ import java.util.HashMap; import static org.testng.Assert.assertEquals; +import static org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.TAG_2FA; +import static org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.TAG_CUSTOM; public class UserDefinedAuthenticatorTest { @@ -39,7 +41,7 @@ public void createUserDefinedLocalVerificationAuthenticator() { UserDefinedLocalAuthenticatorConfig config = new UserDefinedLocalAuthenticatorConfig(AuthenticatorPropertyConstants.AuthenticationType.VERIFICATION); - assertEquals(config.getTags(), new String[]{"CUSTOM", "2FA"}); + assertEquals(config.getTags(), new String[]{TAG_CUSTOM, TAG_2FA}); assertEquals(config.getDefinedByType(), AuthenticatorPropertyConstants.DefinedByType.USER); } @@ -49,7 +51,7 @@ public void createUserDefinedLocalIdentificationAuthenticator() { UserDefinedLocalAuthenticatorConfig config = new UserDefinedLocalAuthenticatorConfig( AuthenticatorPropertyConstants.AuthenticationType.IDENTIFICATION); - assertEquals(config.getTags(), new String[]{"CUSTOM"}); + assertEquals(config.getTags(), new String[]{TAG_CUSTOM}); assertEquals(config.getDefinedByType(), AuthenticatorPropertyConstants.DefinedByType.USER); } @@ -57,7 +59,7 @@ public void createUserDefinedLocalIdentificationAuthenticator() { public void createUserDefinedFederatedAuthenticator() { UserDefinedFederatedAuthenticatorConfig config = new UserDefinedFederatedAuthenticatorConfig(); - assertEquals(config.getTags(), new String[]{"CUSTOM"}); + assertEquals(config.getTags(), new String[]{TAG_CUSTOM}); assertEquals(config.getDefinedByType(), AuthenticatorPropertyConstants.DefinedByType.USER); } diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/dao/AuthenticatorManagementDAOImplTest.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/dao/AuthenticatorManagementDAOImplTest.java new file mode 100644 index 000000000000..ef4b5ba57c49 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/dao/AuthenticatorManagementDAOImplTest.java @@ -0,0 +1,176 @@ +/* + * 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.model.test.dao; + +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.application.common.dao.impl.AuthenticatorManagementDAOImpl; +import org.wso2.carbon.identity.application.common.exception.AuthenticatorMgtException; +import org.wso2.carbon.identity.application.common.model.Property; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.test.util.UserDefinedLocalAuthenticatorDataUtil; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.common.testng.WithH2Database; +import org.wso2.carbon.identity.common.testng.WithRealmService; +import org.wso2.carbon.identity.core.internal.IdentityCoreServiceDataHolder; + +import static org.junit.Assert.assertThrows; +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError.ERROR_WHILE_ADDING_AUTHENTICATOR; +import static org.wso2.carbon.identity.application.common.util.AuthenticatorMgtExceptionBuilder.AuthenticatorMgtError.ERROR_WHILE_UPDATING_AUTHENTICATOR; + +@WithH2Database(files = {"dbscripts/h2.sql"}) +@WithCarbonHome +@WithRealmService(injectToSingletons = {IdentityCoreServiceDataHolder.class}) +public class AuthenticatorManagementDAOImplTest { + + private final int tenantId = -1234; + + private UserDefinedLocalAuthenticatorConfig authenticatorConfig1; + private UserDefinedLocalAuthenticatorConfig authenticatorConfig2; + private UserDefinedLocalAuthenticatorConfig authenticatorConfigForException; + private UserDefinedLocalAuthenticatorConfig authenticatorForUpdate; + private UserDefinedLocalAuthenticatorConfig authenticatorForUpdateForException; + + private static final String AUTHENTICATOR1_NAME = "auth1"; + private static final String AUTHENTICATOR2_NAME = "auth2"; + private static final String AUTHENTICATOR_CONFIG_FOR_EXCEPTION_NAME = "exception_auth"; + private static final String NON_EXIST_AUTHENTICATOR_NAME = "non_exist_auth"; + + private final AuthenticatorManagementDAOImpl authenticatorManagementDAO = new AuthenticatorManagementDAOImpl(); + + @BeforeClass + public void setUpClass() { + + authenticatorConfig1 = UserDefinedLocalAuthenticatorDataUtil.createUserDefinedAuthenticatorConfig + (AUTHENTICATOR1_NAME, AuthenticatorPropertyConstants.AuthenticationType.IDENTIFICATION); + authenticatorConfig2 = UserDefinedLocalAuthenticatorDataUtil.createUserDefinedAuthenticatorConfig( + AUTHENTICATOR2_NAME, AuthenticatorPropertyConstants.AuthenticationType.VERIFICATION); + authenticatorForUpdate = UserDefinedLocalAuthenticatorDataUtil.updateUserDefinedAuthenticatorConfig( + authenticatorConfig1); + authenticatorForUpdateForException = UserDefinedLocalAuthenticatorDataUtil + .updateUserDefinedAuthenticatorConfigForSQLException(authenticatorConfig1); + authenticatorConfigForException = UserDefinedLocalAuthenticatorDataUtil + .createUserDefinedAuthenticatorConfigForSQLException( + AUTHENTICATOR_CONFIG_FOR_EXCEPTION_NAME, + AuthenticatorPropertyConstants.AuthenticationType.IDENTIFICATION); + + } + + @DataProvider(name = "authenticatorConfig") + public Object[][] authenticatorConfig() { + + return new Object[][]{ + {authenticatorConfig1}, + {authenticatorConfig2} + }; + } + + @Test(dataProvider = "authenticatorConfig", priority = 1) + public void testAddUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig config) + throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig createdAuthenticator = authenticatorManagementDAO + .addUserDefinedLocalAuthenticator(config, tenantId); + Assert.assertNotNull(createdAuthenticator); + Assert.assertEquals(createdAuthenticator.getName(), config.getName()); + Assert.assertEquals(createdAuthenticator.getDisplayName(), config.getDisplayName()); + Assert.assertEquals(createdAuthenticator.isEnabled(), config.isEnabled()); + Assert.assertEquals(createdAuthenticator.getDefinedByType(), config.getDefinedByType()); + } + + @Test(priority = 2) + public void testAddUserDefinedLocalAuthenticatorWithSQLException() { + + AuthenticatorMgtException exception = assertThrows(AuthenticatorMgtException.class, () -> + authenticatorManagementDAO.addUserDefinedLocalAuthenticator(authenticatorConfigForException, tenantId)); + Assert.assertEquals(exception.getErrorCode(), ERROR_WHILE_ADDING_AUTHENTICATOR.getCode()); + } + + @Test(priority = 3) + public void testAddUserDefinedLocalAuthenticatorWithOutActionProperty() { + + authenticatorConfigForException.setProperties(new Property[0]); + AuthenticatorMgtException exception = assertThrows(AuthenticatorMgtException.class, () -> + authenticatorManagementDAO.addUserDefinedLocalAuthenticator(authenticatorConfigForException, tenantId)); + Assert.assertEquals(exception.getErrorCode(), ERROR_WHILE_ADDING_AUTHENTICATOR.getCode()); + } + + @Test(priority = 4) + public void testUpdateUserDefinedLocalAuthenticator() throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig updatedConfig = authenticatorManagementDAO + .updateUserDefinedLocalAuthenticator(authenticatorConfig1, authenticatorForUpdate, tenantId); + Assert.assertNotNull(updatedConfig); + Assert.assertEquals(updatedConfig.getName(), authenticatorForUpdate.getName()); + Assert.assertEquals(updatedConfig.getDisplayName(), authenticatorForUpdate.getDisplayName()); + Assert.assertEquals(updatedConfig.isEnabled(), authenticatorForUpdate.isEnabled()); + Assert.assertEquals(updatedConfig.getDefinedByType(), authenticatorForUpdate.getDefinedByType()); + + authenticatorConfig1 = authenticatorForUpdate; + } + + @Test(priority = 5) + public void testUpdateUserDefinedLocalAuthenticatorForException() { + + AuthenticatorMgtException exception = assertThrows(AuthenticatorMgtException.class, () -> + authenticatorManagementDAO.updateUserDefinedLocalAuthenticator(authenticatorConfig1, + authenticatorForUpdateForException, tenantId)); + Assert.assertEquals(exception.getErrorCode(), ERROR_WHILE_UPDATING_AUTHENTICATOR.getCode()); + } + + @Test(dataProvider = "authenticatorConfig", priority = 6) + public void testGetUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig config) + throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig retrievedConfig = authenticatorManagementDAO + .getUserDefinedLocalAuthenticator(config.getName(), tenantId); + Assert.assertNotNull(retrievedConfig); + Assert.assertEquals(retrievedConfig.getName(), config.getName()); + Assert.assertEquals(retrievedConfig.getDisplayName(), config.getDisplayName()); + Assert.assertEquals(retrievedConfig.isEnabled(), config.isEnabled()); + Assert.assertEquals(retrievedConfig.getDefinedByType(), config.getDefinedByType()); + } + + @Test(priority = 7) + public void testGetNonExistingUserDefinedLocalAuthenticator() throws AuthenticatorMgtException { + + UserDefinedLocalAuthenticatorConfig config = authenticatorManagementDAO.getUserDefinedLocalAuthenticator( + AUTHENTICATOR_CONFIG_FOR_EXCEPTION_NAME, tenantId); + + Assert.assertNull(config); + } + + @Test(priority = 8) + public void testGetUserDefinedLocalAuthenticatorForNonExist() throws AuthenticatorMgtException { + + Assert.assertNull(authenticatorManagementDAO.getUserDefinedLocalAuthenticator( + NON_EXIST_AUTHENTICATOR_NAME, tenantId)); + } + + @Test(dataProvider = "authenticatorConfig", priority = 9) + public void testDeleteUserDefinedLocalAuthenticator(UserDefinedLocalAuthenticatorConfig config) + throws AuthenticatorMgtException { + + authenticatorManagementDAO.deleteUserDefinedLocalAuthenticator(config.getName(), config, tenantId); + Assert.assertNull(authenticatorManagementDAO.getUserDefinedLocalAuthenticator(config.getName(), tenantId)); + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/util/ActionMgtTestUtil.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/util/ActionMgtTestUtil.java new file mode 100644 index 000000000000..810cfd73a976 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/util/ActionMgtTestUtil.java @@ -0,0 +1,69 @@ +/* + * 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.model.test.util; + +import org.wso2.carbon.identity.action.management.exception.ActionMgtException; +import org.wso2.carbon.identity.action.management.model.Action; +import org.wso2.carbon.identity.action.management.model.Authentication; +import org.wso2.carbon.identity.action.management.model.EndpointConfig; +import org.wso2.carbon.identity.action.management.service.ActionManagementService; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ActionMgtTestUtil { + + public static final String ASSOCIATED_ACTION_ID = "Dummy_Action_ID"; + + public static Action createAction(EndpointConfig endpointConfig) { + + Action.ActionResponseBuilder actionResponseBuilder = new Action.ActionResponseBuilder(); + actionResponseBuilder.id(ASSOCIATED_ACTION_ID); + actionResponseBuilder.name("SampleAssociatedAction"); + actionResponseBuilder.type(Action.ActionTypes.AUTHENTICATION); + actionResponseBuilder.description("SampleDescription"); + actionResponseBuilder.status(Action.Status.ACTIVE); + actionResponseBuilder.endpoint(endpointConfig); + return actionResponseBuilder.build(); + } + + public static EndpointConfig createEndpointConfig(String uri, String username, String password) { + + EndpointConfig.EndpointConfigBuilder endpointConfigBuilder = new EndpointConfig.EndpointConfigBuilder(); + endpointConfigBuilder.uri(uri); + endpointConfigBuilder.authentication( + new Authentication.BasicAuthBuilder(username, password).build()); + return endpointConfigBuilder.build(); + } + + public static ActionManagementService mockActionService(Action action) throws ActionMgtException { + + ActionManagementService actionManagementService = mock(ActionManagementService.class); + + when(actionManagementService.addAction(anyString(), any(), any())).thenReturn(action); + when(actionManagementService.updateAction(anyString(), any(), any(), any())).thenReturn(action); + when(actionManagementService.getActionByActionId(anyString(), any(), any())).thenReturn(action); + doNothing().when(actionManagementService).deleteAction(anyString(), any(), any()); + + return actionManagementService; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/util/UserDefinedLocalAuthenticatorDataUtil.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/util/UserDefinedLocalAuthenticatorDataUtil.java new file mode 100644 index 000000000000..52d82d6421ba --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/java/org/wso2/carbon/identity/application/common/model/test/util/UserDefinedLocalAuthenticatorDataUtil.java @@ -0,0 +1,164 @@ +/* + * 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.model.test.util; + +import com.google.gson.Gson; +import org.wso2.carbon.identity.action.management.model.Authentication; +import org.wso2.carbon.identity.application.common.model.LocalAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.Property; +import org.wso2.carbon.identity.application.common.model.UserDefinedAuthenticatorEndpointConfig.UserDefinedAuthenticatorEndpointConfigBuilder; +import org.wso2.carbon.identity.application.common.model.UserDefinedLocalAuthenticatorConfig; +import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants; + +import java.util.HashMap; + +public class UserDefinedLocalAuthenticatorDataUtil { + + private static final Gson gson = new Gson(); + + /** + * Create a user defined authenticator configuration. + * + * @param uniqueIdentifier Unique identifier for the authenticator. + * @param type Authentication type. + * @return UserDefinedLocalAuthenticatorConfig + */ + public static UserDefinedLocalAuthenticatorConfig createUserDefinedAuthenticatorConfig(String uniqueIdentifier, + AuthenticatorPropertyConstants.AuthenticationType type) { + + UserDefinedLocalAuthenticatorConfig authenticatorConfig = new + UserDefinedLocalAuthenticatorConfig(AuthenticatorPropertyConstants.AuthenticationType.IDENTIFICATION); + authenticatorConfig.setName(uniqueIdentifier); + authenticatorConfig.setDisplayName("Custom " + uniqueIdentifier); + authenticatorConfig.setEnabled(true); + authenticatorConfig.setDefinedByType(AuthenticatorPropertyConstants.DefinedByType.USER); + authenticatorConfig.setAuthenticationType(type); + authenticatorConfig.setProperties(buildAuthenticatorProperties()); + UserDefinedAuthenticatorEndpointConfigBuilder endpointConfigBuilder = buildAuthenticatorEndpointConfig(); + authenticatorConfig.setEndpointConfig(endpointConfigBuilder.build()); + + return authenticatorConfig; + } + + /** + * Create a system defined authenticator configuration. + * + * @param uniqueIdentifier Unique identifier for the authenticator. + * @return LocalAuthenticatorConfig + */ + public static LocalAuthenticatorConfig createSystemDefinedAuthenticatorConfig(String uniqueIdentifier) { + + LocalAuthenticatorConfig authenticatorConfig = new LocalAuthenticatorConfig(); + authenticatorConfig.setName(uniqueIdentifier); + authenticatorConfig.setDisplayName("Custom " + uniqueIdentifier); + authenticatorConfig.setEnabled(true); + authenticatorConfig.setDefinedByType(AuthenticatorPropertyConstants.DefinedByType.SYSTEM); + Property prop1 = new Property(); + prop1.setName("PropertyName1_" + uniqueIdentifier); + prop1.setValue("PropertyValue1_" + uniqueIdentifier); + prop1.setConfidential(false); + Property prop2 = new Property(); + prop2.setName("PropertyName2_" + uniqueIdentifier); + prop2.setValue("PropertyValue2_" + uniqueIdentifier); + prop2.setConfidential(true); + authenticatorConfig.setProperties(new Property[]{prop1, prop2}); + + return authenticatorConfig; + } + + /** + * Create a user defined authenticator configuration for an SQL exception. + * + * @param uniqueIdentifier Unique identifier for the authenticator. + * @param type Authentication type. + * @return UserDefinedLocalAuthenticatorConfig + */ + public static UserDefinedLocalAuthenticatorConfig createUserDefinedAuthenticatorConfigForSQLException( + String uniqueIdentifier, AuthenticatorPropertyConstants.AuthenticationType type) { + + UserDefinedLocalAuthenticatorConfig authenticatorConfigForException = + createUserDefinedAuthenticatorConfig(uniqueIdentifier, type); + authenticatorConfigForException.setDisplayName("Authenticator name with 254 characters".repeat(50)); + + return authenticatorConfigForException; + } + + /** + * Build the endpoint configuration for the user defined authenticator. + * + * @return UserDefinedAuthenticatorEndpointConfigBuilder + */ + public static UserDefinedAuthenticatorEndpointConfigBuilder buildAuthenticatorEndpointConfig() { + + UserDefinedAuthenticatorEndpointConfigBuilder endpointConfigBuilder = + new UserDefinedAuthenticatorEndpointConfigBuilder(); + endpointConfigBuilder.uri("https://localhost:8080/test"); + endpointConfigBuilder.authenticationType(Authentication.Type.BASIC.getName()); + HashMap authProperties = new HashMap<>(); + authProperties.put("username", "admin"); + authProperties.put("password", "admin"); + endpointConfigBuilder.authenticationProperties(authProperties); + return endpointConfigBuilder; + } + + /** + * Update the user defined authenticator configuration. + * + * @param authenticatorConfig UserDefinedLocalAuthenticatorConfig + * @return UserDefinedLocalAuthenticatorConfig + */ + public static UserDefinedLocalAuthenticatorConfig updateUserDefinedAuthenticatorConfig( + UserDefinedLocalAuthenticatorConfig authenticatorConfig) { + + UserDefinedLocalAuthenticatorConfig updatingConfig = gson.fromJson(gson.toJson(authenticatorConfig), + UserDefinedLocalAuthenticatorConfig.class); + updatingConfig.setName(authenticatorConfig.getName()); + updatingConfig.setDisplayName("UpdatedDisplayName"); + updatingConfig.setEnabled(false); + + return updatingConfig; + } + + public static UserDefinedLocalAuthenticatorConfig updateUserDefinedAuthenticatorConfigForSQLException( + UserDefinedLocalAuthenticatorConfig authenticatorConfig) { + + UserDefinedLocalAuthenticatorConfig updatingConfig = gson.fromJson(gson.toJson(authenticatorConfig), + UserDefinedLocalAuthenticatorConfig.class); + updatingConfig.setName(authenticatorConfig.getName()); + updatingConfig.setEnabled(false); + updatingConfig.setDisplayName("Authenticator name with 254 characters".repeat(50)); + + return updatingConfig; + } + + + /** + * Build the properties for the user defined authenticator. + * + * @return Property[] + */ + public static Property[] buildAuthenticatorProperties() { + + Property property = new Property(); + property.setName("actionId"); + property.setValue("actionId"); + + return new Property[]{property}; + } +} diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/dbscripts/h2.sql b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/dbscripts/h2.sql new file mode 100644 index 000000000000..2460775fdce3 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/dbscripts/h2.sql @@ -0,0 +1,1482 @@ +CREATE TABLE IF NOT EXISTS IDN_BASE_TABLE ( + PRODUCT_NAME VARCHAR (20), + PRIMARY KEY (PRODUCT_NAME) +); + +INSERT INTO IDN_BASE_TABLE values ('WSO2 Identity Server'); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH_CONSUMER_APPS ( + ID INTEGER NOT NULL AUTO_INCREMENT, + CONSUMER_KEY VARCHAR (255), + CONSUMER_SECRET VARCHAR (2048), + USERNAME VARCHAR (255), + TENANT_ID INTEGER DEFAULT 0, + USER_DOMAIN VARCHAR(50), + APP_NAME VARCHAR (255), + OAUTH_VERSION VARCHAR (128), + CALLBACK_URL VARCHAR (2048), + GRANT_TYPES VARCHAR (1024), + PKCE_MANDATORY CHAR(1) DEFAULT '0', + PKCE_SUPPORT_PLAIN CHAR(1) DEFAULT '0', + APP_STATE VARCHAR (25) DEFAULT 'ACTIVE', + USER_ACCESS_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600, + APP_ACCESS_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600, + REFRESH_TOKEN_EXPIRE_TIME BIGINT DEFAULT 84600, + ID_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600, + CONSTRAINT CONSUMER_KEY_CONSTRAINT UNIQUE (TENANT_ID, CONSUMER_KEY), + PRIMARY KEY (ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE_VALIDATORS ( + APP_ID INTEGER NOT NULL, + SCOPE_VALIDATOR VARCHAR (128) NOT NULL, + PRIMARY KEY (APP_ID,SCOPE_VALIDATOR), + FOREIGN KEY (APP_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH1A_REQUEST_TOKEN ( + REQUEST_TOKEN VARCHAR (512), + REQUEST_TOKEN_SECRET VARCHAR (512), + CONSUMER_KEY_ID INTEGER, + CALLBACK_URL VARCHAR (2048), + SCOPE VARCHAR(2048), + AUTHORIZED VARCHAR (128), + OAUTH_VERIFIER VARCHAR (512), + AUTHZ_USER VARCHAR (512), + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (REQUEST_TOKEN), + FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH1A_ACCESS_TOKEN ( + ACCESS_TOKEN VARCHAR (512), + ACCESS_TOKEN_SECRET VARCHAR (512), + CONSUMER_KEY_ID INTEGER, + SCOPE VARCHAR(2048), + AUTHZ_USER VARCHAR (512), + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (ACCESS_TOKEN), + FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN ( + TOKEN_ID VARCHAR (255), + ACCESS_TOKEN VARCHAR (2048), + REFRESH_TOKEN VARCHAR (2048), + CONSUMER_KEY_ID INTEGER, + AUTHZ_USER VARCHAR (100), + TENANT_ID INTEGER, + USER_DOMAIN VARCHAR(50), + USER_TYPE VARCHAR (25), + GRANT_TYPE VARCHAR (50), + TIME_CREATED TIMESTAMP DEFAULT 0, + REFRESH_TOKEN_TIME_CREATED TIMESTAMP DEFAULT 0, + VALIDITY_PERIOD BIGINT, + REFRESH_TOKEN_VALIDITY_PERIOD BIGINT, + TOKEN_SCOPE_HASH VARCHAR (32), + TOKEN_STATE VARCHAR (25) DEFAULT 'ACTIVE', + TOKEN_STATE_ID VARCHAR (128) DEFAULT 'NONE', + SUBJECT_IDENTIFIER VARCHAR(255), + ACCESS_TOKEN_HASH VARCHAR (512), + REFRESH_TOKEN_HASH VARCHAR (512), + IDP_ID INTEGER DEFAULT -1 NOT NULL, + TOKEN_BINDING_REF VARCHAR (32) DEFAULT 'NONE', + CONSENTED_TOKEN VARCHAR(6), + AUTHORIZED_ORGANIZATION VARCHAR(36) DEFAULT 'NONE' NOT NULL, + PRIMARY KEY (TOKEN_ID), + FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE, + CONSTRAINT CON_APP_KEY UNIQUE (CONSUMER_KEY_ID,AUTHZ_USER,TENANT_ID,USER_DOMAIN,USER_TYPE,TOKEN_SCOPE_HASH, + TOKEN_STATE,TOKEN_STATE_ID,IDP_ID,TOKEN_BINDING_REF,AUTHORIZED_ORGANIZATION) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_TOKEN_BINDING ( + TOKEN_ID VARCHAR (255), + TOKEN_BINDING_TYPE VARCHAR (32), + TOKEN_BINDING_REF VARCHAR (32), + TOKEN_BINDING_VALUE VARCHAR (1024), + TENANT_ID INTEGER DEFAULT -1, + UNIQUE (TOKEN_ID,TOKEN_BINDING_TYPE,TOKEN_BINDING_VALUE), + FOREIGN KEY (TOKEN_ID) REFERENCES IDN_OAUTH2_ACCESS_TOKEN(TOKEN_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_AUDIT ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TOKEN_ID VARCHAR (255), + ACCESS_TOKEN VARCHAR(2048), + REFRESH_TOKEN VARCHAR(2048), + CONSUMER_KEY_ID INTEGER, + AUTHZ_USER VARCHAR (100), + TENANT_ID INTEGER, + USER_DOMAIN VARCHAR(50), + USER_TYPE VARCHAR (25), + GRANT_TYPE VARCHAR (50), + TIME_CREATED TIMESTAMP NULL, + REFRESH_TOKEN_TIME_CREATED TIMESTAMP NULL, + VALIDITY_PERIOD BIGINT, + REFRESH_TOKEN_VALIDITY_PERIOD BIGINT, + TOKEN_SCOPE_HASH VARCHAR(32), + TOKEN_STATE VARCHAR(25), + TOKEN_STATE_ID VARCHAR (128) , + SUBJECT_IDENTIFIER VARCHAR(255), + ACCESS_TOKEN_HASH VARCHAR(512), + REFRESH_TOKEN_HASH VARCHAR(512), + INVALIDATED_TIME TIMESTAMP NULL, + IDP_ID INTEGER DEFAULT -1 NOT NULL, + PRIMARY KEY(ID) +); + + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_CODE ( + CODE_ID VARCHAR (255), + AUTHORIZATION_CODE VARCHAR (2048), + CONSUMER_KEY_ID INTEGER, + CALLBACK_URL VARCHAR (2048), + SCOPE VARCHAR(2048), + AUTHZ_USER VARCHAR (100), + TENANT_ID INTEGER, + USER_DOMAIN VARCHAR(50), + TIME_CREATED TIMESTAMP, + VALIDITY_PERIOD BIGINT, + STATE VARCHAR (25) DEFAULT 'ACTIVE', + TOKEN_ID VARCHAR(255), + SUBJECT_IDENTIFIER VARCHAR(255), + PKCE_CODE_CHALLENGE VARCHAR (255), + PKCE_CODE_CHALLENGE_METHOD VARCHAR(128), + AUTHORIZATION_CODE_HASH VARCHAR (512), + IDP_ID INTEGER DEFAULT -1 NOT NULL, + PRIMARY KEY (CODE_ID), + FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHZ_CODE_SCOPE( + CODE_ID VARCHAR(255), + SCOPE VARCHAR(255), + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (CODE_ID, SCOPE), + FOREIGN KEY (CODE_ID) REFERENCES IDN_OAUTH2_AUTHORIZATION_CODE (CODE_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_DEVICE_FLOW ( + CODE_ID VARCHAR(255), + DEVICE_CODE VARCHAR(255), + USER_CODE VARCHAR(25), + QUANTIFIER INTEGER NOT NULL DEFAULT 0, + CONSUMER_KEY_ID INTEGER, + LAST_POLL_TIME TIMESTAMP NOT NULL, + EXPIRY_TIME TIMESTAMP NOT NULL, + TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + POLL_TIME BIGINT, + STATUS VARCHAR (25) DEFAULT 'PENDING', + AUTHZ_USER VARCHAR (100), + TENANT_ID INTEGER, + USER_DOMAIN VARCHAR(50), + IDP_ID INTEGER, + SUBJECT_IDENTIFIER VARCHAR(255), + PRIMARY KEY (DEVICE_CODE), + UNIQUE (CODE_ID), + CONSTRAINT USRCDE_QNTFR_CONSTRAINT UNIQUE (USER_CODE, QUANTIFIER), + FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_DEVICE_FLOW_SCOPES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + SCOPE_ID VARCHAR(255), + SCOPE VARCHAR(255), + PRIMARY KEY (ID), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_DEVICE_FLOW(CODE_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_SCOPE ( + TOKEN_ID VARCHAR (255), + TOKEN_SCOPE VARCHAR (255), + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (TOKEN_ID, TOKEN_SCOPE), + FOREIGN KEY (TOKEN_ID) REFERENCES IDN_OAUTH2_ACCESS_TOKEN(TOKEN_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE ( + SCOPE_ID INTEGER NOT NULL AUTO_INCREMENT, + NAME VARCHAR(255) NOT NULL, + DISPLAY_NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(512), + TENANT_ID INTEGER NOT NULL DEFAULT -1, + SCOPE_TYPE VARCHAR(255) NOT NULL, + PRIMARY KEY (SCOPE_ID), + UNIQUE (NAME, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE_BINDING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + SCOPE_ID INTEGER NOT NULL, + SCOPE_BINDING VARCHAR(255) NOT NULL, + BINDING_TYPE VARCHAR(255) NOT NULL, + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE(SCOPE_ID) ON DELETE CASCADE, + UNIQUE (SCOPE_ID, SCOPE_BINDING, BINDING_TYPE), + PRIMARY KEY (ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_RESOURCE_SCOPE ( + RESOURCE_PATH VARCHAR(255) NOT NULL, + SCOPE_ID INTEGER NOT NULL, + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (RESOURCE_PATH), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_SCIM_GROUP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR(255) NOT NULL, + ATTR_NAME VARCHAR(1024) NOT NULL, + ATTR_VALUE VARCHAR(1024), + AUDIENCE_REF_ID INTEGER DEFAULT -1 NOT NULL, + UNIQUE(TENANT_ID, ROLE_NAME, ATTR_NAME, AUDIENCE_REF_ID), + PRIMARY KEY (ID) +); + + + +CREATE TABLE IF NOT EXISTS IDN_OPENID_REMEMBER_ME ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + COOKIE_VALUE VARCHAR(1024), + CREATED_TIME TIMESTAMP, + PRIMARY KEY (USER_NAME, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OPENID_USER_RPS ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + RP_URL VARCHAR(255) NOT NULL, + TRUSTED_ALWAYS VARCHAR(128) DEFAULT 'FALSE', + LAST_VISIT DATE NOT NULL, + VISIT_COUNT INTEGER DEFAULT 0, + DEFAULT_PROFILE_NAME VARCHAR(255) DEFAULT 'DEFAULT', + PRIMARY KEY (USER_NAME, TENANT_ID, RP_URL) +); + +CREATE TABLE IF NOT EXISTS IDN_OPENID_ASSOCIATIONS ( + HANDLE VARCHAR(255) NOT NULL, + ASSOC_TYPE VARCHAR(255) NOT NULL, + EXPIRE_IN TIMESTAMP NOT NULL, + MAC_KEY VARCHAR(255) NOT NULL, + ASSOC_STORE VARCHAR(128) DEFAULT 'SHARED', + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (HANDLE) +); + +CREATE TABLE IDN_STS_STORE ( + ID INTEGER AUTO_INCREMENT, + TOKEN_ID VARCHAR(255) NOT NULL, + TOKEN_CONTENT BLOB(1024) NOT NULL, + CREATE_DATE TIMESTAMP NOT NULL, + EXPIRE_DATE TIMESTAMP NOT NULL, + STATE INTEGER DEFAULT 0, + PRIMARY KEY (ID) +); + +CREATE TABLE IDN_IDENTITY_USER_DATA ( + TENANT_ID INTEGER DEFAULT -1234, + USER_NAME VARCHAR(255) NOT NULL, + DATA_KEY VARCHAR(255) NOT NULL, + DATA_VALUE VARCHAR(2048), + PRIMARY KEY (TENANT_ID, USER_NAME, DATA_KEY) +); + +CREATE TABLE IDN_IDENTITY_META_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + METADATA_TYPE VARCHAR(255) NOT NULL, + METADATA VARCHAR(255) NOT NULL, + VALID VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, METADATA_TYPE,METADATA) +); + +CREATE TABLE IF NOT EXISTS IDN_THRIFT_SESSION ( + SESSION_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + CREATED_TIME VARCHAR(255) NOT NULL, + LAST_MODIFIED_TIME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (SESSION_ID) +); + +CREATE TABLE IDN_AUTH_SESSION_STORE ( + SESSION_ID VARCHAR (100) NOT NULL, + SESSION_TYPE VARCHAR(100) NOT NULL, + OPERATION VARCHAR(10) NOT NULL, + SESSION_OBJECT BLOB, + TIME_CREATED BIGINT, + TENANT_ID INTEGER DEFAULT -1, + EXPIRY_TIME BIGINT, + PRIMARY KEY (SESSION_ID, SESSION_TYPE, TIME_CREATED, OPERATION) +); + + +CREATE TABLE IDN_AUTH_TEMP_SESSION_STORE ( + SESSION_ID VARCHAR (100) NOT NULL, + SESSION_TYPE VARCHAR(100) NOT NULL, + OPERATION VARCHAR(10) NOT NULL, + SESSION_OBJECT BLOB, + TIME_CREATED BIGINT, + TENANT_ID INTEGER DEFAULT -1, + EXPIRY_TIME BIGINT, + PRIMARY KEY (SESSION_ID, SESSION_TYPE, TIME_CREATED, OPERATION) +); + +CREATE TABLE IF NOT EXISTS IDN_AUTH_USER ( + USER_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + DOMAIN_NAME VARCHAR(255) NOT NULL, + IDP_ID INTEGER NOT NULL, + PRIMARY KEY (USER_ID), + CONSTRAINT USER_STORE_CONSTRAINT UNIQUE (USER_NAME, TENANT_ID, DOMAIN_NAME, IDP_ID)); + +CREATE TABLE IF NOT EXISTS IDN_AUTH_USER_SESSION_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + USER_ID VARCHAR(255) NOT NULL, + SESSION_ID VARCHAR(255) NOT NULL, + CONSTRAINT USER_SESSION_STORE_CONSTRAINT UNIQUE (USER_ID, SESSION_ID), + PRIMARY KEY (ID)); + +CREATE TABLE IF NOT EXISTS IDN_AUTH_SESSION_APP_INFO ( + SESSION_ID VARCHAR (100) NOT NULL, + SUBJECT VARCHAR (100) NOT NULL, + APP_ID INTEGER NOT NULL, + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + PRIMARY KEY (SESSION_ID, SUBJECT, APP_ID, INBOUND_AUTH_TYPE)); + +CREATE TABLE IF NOT EXISTS IDN_AUTH_SESSION_META_DATA ( + SESSION_ID VARCHAR (100) NOT NULL, + PROPERTY_TYPE VARCHAR (100) NOT NULL, + `VALUE` VARCHAR (255) NOT NULL, + PRIMARY KEY (SESSION_ID, PROPERTY_TYPE, `VALUE`) + ); + +CREATE TABLE IF NOT EXISTS SP_APP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + APP_NAME VARCHAR (255) NOT NULL , + USER_STORE VARCHAR (255) NOT NULL, + USERNAME VARCHAR (255) NOT NULL , + DESCRIPTION VARCHAR (1024), + ROLE_CLAIM VARCHAR (512), + AUTH_TYPE VARCHAR (255) NOT NULL, + PROVISIONING_USERSTORE_DOMAIN VARCHAR (512), + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '1', + IS_SEND_LOCAL_SUBJECT_ID CHAR(1) DEFAULT '0', + IS_SEND_AUTH_LIST_OF_IDPS CHAR(1) DEFAULT '0', + IS_USE_TENANT_DOMAIN_SUBJECT CHAR(1) DEFAULT '1', + IS_USE_USER_DOMAIN_SUBJECT CHAR(1) DEFAULT '1', + ENABLE_AUTHORIZATION CHAR(1) DEFAULT '0', + SUBJECT_CLAIM_URI VARCHAR (512), + IS_SAAS_APP CHAR(1) DEFAULT '0', + IS_DUMB_MODE CHAR(1) DEFAULT '0', + UUID CHAR(36), + IMAGE_URL VARCHAR(1024), + ACCESS_URL VARCHAR(1024), + IS_DISCOVERABLE CHAR(1) DEFAULT '0', + + PRIMARY KEY (ID)); + +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_NAME_CONSTRAINT UNIQUE(APP_NAME, TENANT_ID); +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_UUID_CONSTRAINT UNIQUE(UUID); + +CREATE TABLE IF NOT EXISTS SP_METADATA ( + ID INTEGER AUTO_INCREMENT, + SP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + `VALUE` VARCHAR(255) NOT NULL, + DISPLAY_NAME VARCHAR(255), + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (ID), + CONSTRAINT SP_METADATA_CONSTRAINT UNIQUE (SP_ID, NAME), + FOREIGN KEY (SP_ID) REFERENCES SP_APP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS SP_INBOUND_AUTH ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + INBOUND_AUTH_KEY VARCHAR (255), + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + INBOUND_CONFIG_TYPE VARCHAR (255) NOT NULL, + PROP_NAME VARCHAR (255), + PROP_VALUE VARCHAR (1024) , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_INBOUND_AUTH ADD CONSTRAINT APPLICATION_ID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_AUTH_STEP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + STEP_ORDER INTEGER DEFAULT 1, + APP_ID INTEGER NOT NULL , + IS_SUBJECT_STEP CHAR(1) DEFAULT '0', + IS_ATTRIBUTE_STEP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID)); + +ALTER TABLE SP_AUTH_STEP ADD CONSTRAINT APPLICATION_ID_CONSTRAINT_STEP FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_FEDERATED_IDP ( + ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_ID INTEGER NOT NULL, + PRIMARY KEY (ID, AUTHENTICATOR_ID)); + +ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_CLAIM_DIALECT ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + SP_DIALECT VARCHAR (512) NOT NULL, + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_CLAIM_DIALECT ADD CONSTRAINT DIALECTID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_CLAIM VARCHAR (512) NOT NULL , + SP_CLAIM VARCHAR (512) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_REQUESTED VARCHAR(128) DEFAULT '0', + IS_MANDATORY VARCHAR(128) DEFAULT '0', + DEFAULT_VALUE VARCHAR(255), + PRIMARY KEY (ID)); + +ALTER TABLE SP_CLAIM_MAPPING ADD CONSTRAINT CLAIMID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_ROLE_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_ROLE VARCHAR (255) NOT NULL , + SP_ROLE VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_ROLE_MAPPING ADD CONSTRAINT ROLEID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_REQ_PATH_AUTHENTICATOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_REQ_PATH_AUTHENTICATOR ADD CONSTRAINT REQ_AUTH_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_PROVISIONING_CONNECTOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_NAME VARCHAR (255) NOT NULL , + CONNECTOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_JIT_ENABLED CHAR(1) NOT NULL DEFAULT '0', + BLOCKING CHAR(1) NOT NULL DEFAULT '0', + RULE_ENABLED CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID)); + +ALTER TABLE SP_PROVISIONING_CONNECTOR ADD CONSTRAINT PRO_CONNECTOR_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_AUTH_SCRIPT ( + ID INTEGER AUTO_INCREMENT NOT NULL, + TENANT_ID INTEGER NOT NULL, + APP_ID INTEGER NOT NULL, + TYPE VARCHAR(255) NOT NULL, + CONTENT BLOB DEFAULT NULL, + IS_ENABLED CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID)); + +CREATE TABLE SP_TEMPLATE ( + ID INTEGER AUTO_INCREMENT NOT NULL, + TENANT_ID INTEGER NOT NULL, + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(1023), + CONTENT BLOB DEFAULT NULL, + PRIMARY KEY (ID), + CONSTRAINT SP_TEMPLATE_CONSTRAINT UNIQUE (TENANT_ID, NAME)); + +CREATE TABLE IF NOT EXISTS SP_TRUSTED_APPS ( + ID INTEGER AUTO_INCREMENT, + SP_ID INTEGER NOT NULL, + PLATFORM_TYPE VARCHAR(255) NOT NULL, + APP_IDENTIFIER VARCHAR(255) NOT NULL, + THUMBPRINTS VARCHAR(2048), + IS_FIDO_TRUSTED BOOLEAN DEFAULT FALSE, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + UNIQUE (SP_ID, PLATFORM_TYPE), + FOREIGN KEY (SP_ID) REFERENCES SP_APP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDN_AUTH_WAIT_STATUS ( + ID INTEGER AUTO_INCREMENT NOT NULL, + TENANT_ID INTEGER NOT NULL, + LONG_WAIT_KEY VARCHAR(255) NOT NULL, + WAIT_STATUS CHAR(1) NOT NULL DEFAULT '1', + TIME_CREATED TIMESTAMP DEFAULT 0, + EXPIRE_TIME TIMESTAMP DEFAULT 0, + PRIMARY KEY (ID), + CONSTRAINT IDN_AUTH_WAIT_STATUS_KEY UNIQUE (LONG_WAIT_KEY)); + +CREATE TABLE IF NOT EXISTS IDP ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + NAME VARCHAR(254) NOT NULL, + IS_ENABLED CHAR(1) NOT NULL DEFAULT '1', + IS_PRIMARY CHAR(1) NOT NULL DEFAULT '0', + HOME_REALM_ID VARCHAR(254), + IMAGE MEDIUMBLOB, + CERTIFICATE BLOB, + ALIAS VARCHAR(254), + INBOUND_PROV_ENABLED CHAR(1) NOT NULL DEFAULT '0', + INBOUND_PROV_USER_STORE_ID VARCHAR(254), + USER_CLAIM_URI VARCHAR(254), + ROLE_CLAIM_URI VARCHAR(254), + DESCRIPTION VARCHAR(1024), + DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), + DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), + PROVISIONING_ROLE VARCHAR(128), + IS_FEDERATION_HUB CHAR(1) NOT NULL DEFAULT '0', + IS_LOCAL_CLAIM_DIALECT CHAR(1) NOT NULL DEFAULT '0', + DISPLAY_NAME VARCHAR(255), + IMAGE_URL VARCHAR(1024), + UUID CHAR(36) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, NAME), + UNIQUE (UUID) +); + +CREATE TABLE IF NOT EXISTS IDP_ROLE ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + ROLE VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, ROLE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_GROUP ( + ID INTEGER AUTO_INCREMENT NOT NULL, + IDP_ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + GROUP_NAME VARCHAR(255) NOT NULL, + UUID CHAR(36) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (IDP_ID, GROUP_NAME), + UNIQUE (UUID), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_ROLE_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_ROLE_ID INTEGER, + TENANT_ID INTEGER, + USER_STORE_ID VARCHAR (253), + LOCAL_ROLE VARCHAR(253), + PRIMARY KEY (ID), + UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), + FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_CLAIM ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, CLAIM), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_CLAIM_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_CLAIM_ID INTEGER, + TENANT_ID INTEGER, + LOCAL_CLAIM VARCHAR(253), + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), + FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '1', + DISPLAY_NAME VARCHAR(255), + DEFINED_BY VARCHAR(25) NOT NULL, + AUTHENTICATION_TYPE VARCHAR(25) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_METADATA ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + `VALUE` VARCHAR(255) NOT NULL, + DISPLAY_NAME VARCHAR(255), + TENANT_ID INTEGER DEFAULT -1, + PRIMARY KEY (ID), + CONSTRAINT IDP_METADATA_CONSTRAINT UNIQUE (IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + AUTHENTICATOR_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), + FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_CONFIG ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '0', + IS_BLOCKING CHAR (1) DEFAULT '0', + IS_RULES_ENABLED CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_PROV_CONFIG_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048), + PROPERTY_BLOB_VALUE BLOB, + PROPERTY_TYPE VARCHAR(32) NOT NULL, + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, PROVISIONING_CONFIG_ID, PROPERTY_KEY), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_ENTITY ( + ID INTEGER AUTO_INCREMENT, + PROVISIONING_CONFIG_ID INTEGER, + ENTITY_TYPE VARCHAR(255) NOT NULL, + ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, + ENTITY_NAME VARCHAR(255) NOT NULL, + ENTITY_VALUE VARCHAR(255), + TENANT_ID INTEGER, + ENTITY_LOCAL_ID VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME, PROVISIONING_CONFIG_ID), + UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_LOCAL_CLAIM ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + CLAIM_URI VARCHAR(255) NOT NULL, + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, CLAIM_URI), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDN_ASSOCIATED_ID ( + ID INTEGER AUTO_INCREMENT, + IDP_USER_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + IDP_ID INTEGER NOT NULL, + DOMAIN_NAME VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + ASSOCIATION_ID CHAR(36) NOT NULL, + PRIMARY KEY (ID), + UNIQUE(IDP_USER_ID, TENANT_ID, IDP_ID), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_USER_ACCOUNT_ASSOCIATION ( + ASSOCIATION_KEY VARCHAR(255) NOT NULL, + TENANT_ID INTEGER, + DOMAIN_NAME VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, DOMAIN_NAME, USER_NAME)); + +CREATE TABLE IF NOT EXISTS FIDO_DEVICE_STORE ( + TENANT_ID INTEGER, + DOMAIN_NAME VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(45) NOT NULL, + TIME_REGISTERED TIMESTAMP, + KEY_HANDLE VARCHAR(200) NOT NULL, + DEVICE_DATA VARCHAR(2048) NOT NULL, + PRIMARY KEY (TENANT_ID, DOMAIN_NAME, USER_NAME, KEY_HANDLE)); + +CREATE TABLE IF NOT EXISTS FIDO2_DEVICE_STORE ( + TENANT_ID INTEGER, + DOMAIN_NAME VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(45) NOT NULL, + TIME_REGISTERED TIMESTAMP, + USER_HANDLE VARCHAR(200) NOT NULL, + CREDENTIAL_ID VARCHAR(200) NOT NULL, + PUBLIC_KEY_COSE VARCHAR(2048) NOT NULL, + SIGNATURE_COUNT BIGINT, + USER_IDENTITY VARCHAR(200) NOT NULL, + DISPLAY_NAME VARCHAR(255), + IS_USERNAMELESS_SUPPORTED CHAR(1) DEFAULT '0', + PRIMARY KEY (CREDENTIAL_ID, USER_HANDLE)); + +CREATE TABLE IF NOT EXISTS IDN_RECOVERY_FLOW_DATA ( + RECOVERY_FLOW_ID VARCHAR(255) NOT NULL, + CODE VARCHAR(255), + FAILED_ATTEMPTS INTEGER DEFAULT 0 NOT NULL, + RESEND_COUNT INTEGER DEFAULT 0 NOT NULL, + TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(RECOVERY_FLOW_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_RECOVERY_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + USER_DOMAIN VARCHAR(127) NOT NULL, + TENANT_ID INTEGER DEFAULT -1, + CODE VARCHAR(255) NOT NULL, + SCENARIO VARCHAR(255) NOT NULL, + STEP VARCHAR(127) NOT NULL, + TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + REMAINING_SETS VARCHAR(2500) DEFAULT NULL, + RECOVERY_FLOW_ID VARCHAR(255), + PRIMARY KEY(USER_NAME, USER_DOMAIN, TENANT_ID, SCENARIO,STEP), + FOREIGN KEY (RECOVERY_FLOW_ID) REFERENCES IDN_RECOVERY_FLOW_DATA(RECOVERY_FLOW_ID) ON DELETE CASCADE, + UNIQUE(CODE) +); + +CREATE TABLE IF NOT EXISTS IDN_PASSWORD_HISTORY_DATA ( + ID INTEGER NOT NULL AUTO_INCREMENT, + USER_NAME VARCHAR(255) NOT NULL, + USER_DOMAIN VARCHAR(127) NOT NULL, + TENANT_ID INTEGER DEFAULT -1, + SALT_VALUE VARCHAR(255), + HASH VARCHAR(255) NOT NULL, + TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + UNIQUE (USER_NAME,USER_DOMAIN,TENANT_ID,SALT_VALUE,HASH) +); + +CREATE TABLE IF NOT EXISTS IDN_CLAIM_DIALECT ( + ID INTEGER NOT NULL AUTO_INCREMENT, + DIALECT_URI VARCHAR (255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT DIALECT_URI_CONSTRAINT UNIQUE (DIALECT_URI, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_CLAIM ( + ID INTEGER NOT NULL AUTO_INCREMENT, + DIALECT_ID INTEGER NOT NULL, + CLAIM_URI VARCHAR (255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (DIALECT_ID) REFERENCES IDN_CLAIM_DIALECT(ID) ON DELETE CASCADE, + CONSTRAINT CLAIM_URI_CONSTRAINT UNIQUE (DIALECT_ID, CLAIM_URI, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_CLAIM_MAPPED_ATTRIBUTE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + LOCAL_CLAIM_ID INTEGER, + USER_STORE_DOMAIN_NAME VARCHAR (255) NOT NULL, + ATTRIBUTE_NAME VARCHAR (255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (LOCAL_CLAIM_ID) REFERENCES IDN_CLAIM(ID) ON DELETE CASCADE, + CONSTRAINT USER_STORE_DOMAIN_CONSTRAINT UNIQUE (LOCAL_CLAIM_ID, USER_STORE_DOMAIN_NAME, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_CLAIM_PROPERTY ( + ID INTEGER NOT NULL AUTO_INCREMENT, + LOCAL_CLAIM_ID INTEGER, + PROPERTY_NAME VARCHAR (255) NOT NULL, + PROPERTY_VALUE VARCHAR (255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (LOCAL_CLAIM_ID) REFERENCES IDN_CLAIM(ID) ON DELETE CASCADE, + CONSTRAINT PROPERTY_NAME_CONSTRAINT UNIQUE (LOCAL_CLAIM_ID, PROPERTY_NAME, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + EXT_CLAIM_ID INTEGER NOT NULL, + MAPPED_LOCAL_CLAIM_ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (EXT_CLAIM_ID) REFERENCES IDN_CLAIM(ID) ON DELETE CASCADE, + FOREIGN KEY (MAPPED_LOCAL_CLAIM_ID) REFERENCES IDN_CLAIM(ID) ON DELETE CASCADE, + CONSTRAINT EXT_TO_LOC_MAPPING_CONSTRN UNIQUE (EXT_CLAIM_ID, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_SAML2_ASSERTION_STORE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + SAML2_ID VARCHAR(255) , + SAML2_ISSUER VARCHAR(255) , + SAML2_SUBJECT VARCHAR(255) , + SAML2_SESSION_INDEX VARCHAR(255) , + SAML2_AUTHN_CONTEXT_CLASS_REF VARCHAR(255) , + SAML2_ASSERTION VARCHAR(4096) , + ASSERTION BLOB , + PRIMARY KEY (ID) +); + +CREATE TABLE IDN_SAML2_ARTIFACT_STORE ( + ID INT NOT NULL AUTO_INCREMENT, + SOURCE_ID VARCHAR(255) NOT NULL, + MESSAGE_HANDLER VARCHAR(255) NOT NULL, + AUTHN_REQ_DTO BLOB NOT NULL, + SESSION_ID VARCHAR(255) NOT NULL, + INIT_TIMESTAMP TIMESTAMP NOT NULL, + EXP_TIMESTAMP TIMESTAMP NOT NULL, + ASSERTION_ID VARCHAR(255), + PRIMARY KEY (`ID`) +); + +CREATE TABLE IF NOT EXISTS IDN_OIDC_JTI ( + JWT_ID VARCHAR(255), + TENANT_ID INTEGER NOT NULL, + EXP_TIME TIMESTAMP NOT NULL , + TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , + PRIMARY KEY (JWT_ID, TENANT_ID) +); + + +CREATE TABLE IF NOT EXISTS IDN_OIDC_PROPERTY ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER, + CONSUMER_KEY VARCHAR(255) , + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047) , + PRIMARY KEY (ID), + FOREIGN KEY (TENANT_ID, CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(TENANT_ID, CONSUMER_KEY) ON DELETE CASCADE +); +CREATE TABLE IF NOT EXISTS IDN_OIDC_REQ_OBJECT_REFERENCE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + CONSUMER_KEY_ID INTEGER , + CODE_ID VARCHAR(255) , + TOKEN_ID VARCHAR(255) , + SESSION_DATA_KEY VARCHAR(255), + PRIMARY KEY (ID), + FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE, + FOREIGN KEY (TOKEN_ID) REFERENCES IDN_OAUTH2_ACCESS_TOKEN(TOKEN_ID) ON DELETE CASCADE, + FOREIGN KEY (CODE_ID) REFERENCES IDN_OAUTH2_AUTHORIZATION_CODE(CODE_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OIDC_REQ_OBJECT_CLAIMS ( + ID INTEGER NOT NULL AUTO_INCREMENT, + REQ_OBJECT_ID INTEGER, + CLAIM_ATTRIBUTE VARCHAR(255) , + ESSENTIAL CHAR(1) NOT NULL DEFAULT '0', + `VALUE` VARCHAR(255) , + IS_USERINFO CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID), + FOREIGN KEY (REQ_OBJECT_ID) REFERENCES IDN_OIDC_REQ_OBJECT_REFERENCE (ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OIDC_REQ_OBJ_CLAIM_VALUES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + REQ_OBJECT_CLAIMS_ID INTEGER , + CLAIM_VALUES VARCHAR(255) , + PRIMARY KEY (ID), + FOREIGN KEY (REQ_OBJECT_CLAIMS_ID) REFERENCES IDN_OIDC_REQ_OBJECT_CLAIMS(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_CERTIFICATE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + NAME VARCHAR(100), + CERTIFICATE_IN_PEM BLOB, + TENANT_ID INTEGER DEFAULT 0, + PRIMARY KEY(ID), + CONSTRAINT CERTIFICATE_UNIQUE_KEY UNIQUE (NAME, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OIDC_SCOPE_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + SCOPE_ID INTEGER NOT NULL, + EXTERNAL_CLAIM_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE(SCOPE_ID) ON DELETE CASCADE, + FOREIGN KEY (EXTERNAL_CLAIM_ID) REFERENCES IDN_CLAIM(ID) ON DELETE CASCADE, + UNIQUE (SCOPE_ID, EXTERNAL_CLAIM_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_FUNCTION_LIBRARY ( + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(1023), + TYPE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + DATA BLOB NOT NULL, + PRIMARY KEY (TENANT_ID,NAME) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_CIBA_AUTH_CODE ( + AUTH_CODE_KEY CHAR (36), + AUTH_REQ_ID CHAR (36), + ISSUED_TIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSUMER_KEY VARCHAR(255), + LAST_POLLED_TIME TIMESTAMP NOT NULL, + POLLING_INTERVAL INTEGER, + EXPIRES_IN INTEGER, + AUTHENTICATED_USER_NAME VARCHAR(255), + USER_STORE_DOMAIN VARCHAR(100), + TENANT_ID INTEGER, + AUTH_REQ_STATUS VARCHAR (100) DEFAULT 'REQUESTED', + IDP_ID INTEGER, + UNIQUE(AUTH_REQ_ID), + PRIMARY KEY (AUTH_CODE_KEY), + FOREIGN KEY (TENANT_ID, CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(TENANT_ID, CONSUMER_KEY) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_CIBA_REQUEST_SCOPES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + AUTH_CODE_KEY CHAR (36), + SCOPE VARCHAR (255), + FOREIGN KEY (AUTH_CODE_KEY) REFERENCES IDN_OAUTH2_CIBA_AUTH_CODE(AUTH_CODE_KEY) ON DELETE CASCADE, + PRIMARY KEY (ID) +); + +CREATE TABLE IF NOT EXISTS IDN_FED_AUTH_SESSION_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + IDP_SESSION_ID VARCHAR(255) NOT NULL, + SESSION_ID VARCHAR(255) NOT NULL, + IDP_NAME VARCHAR(255) NOT NULL, + AUTHENTICATOR_ID VARCHAR(255), + PROTOCOL_TYPE VARCHAR(255), + TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + TENANT_ID INTEGER NOT NULL DEFAULT 0, + IDP_ID INTEGER NOT NULL DEFAULT 0, + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE, + PRIMARY KEY (ID), + UNIQUE (IDP_SESSION_ID, TENANT_ID, IDP_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_CONFIG_TYPE ( + ID VARCHAR(255) NOT NULL, + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(1023) NULL, + PRIMARY KEY (ID), + CONSTRAINT TYPE_NAME_CONSTRAINT UNIQUE (NAME) +); + +INSERT INTO IDN_CONFIG_TYPE (ID, NAME, DESCRIPTION) VALUES +('9ab0ef95-13e9-4ed5-afaf-d29bed62f7bd', 'IDP_TEMPLATE', 'Template type to uniquely identify IDP templates'), +('3c4ac3d0-5903-4e3d-aaca-38df65b33bfd', 'APPLICATION_TEMPLATE', 'Template type to uniquely identify Application templates'), +('8ec6dbf1-218a-49bf-bc34-0d2db52d151c', 'CORS_CONFIGURATION', 'A resource type to keep the tenant CORS configurations'), +('669b99ca-cdb0-44a6-8cae-babed3b585df', 'Publisher', 'A resource type to keep the event publisher configurations'), +('73f6d9ca-62f4-4566-bab9-2a930ae51ba8', 'BRANDING_PREFERENCES', 'A resource type to keep the tenant branding preferences'), +('8469a176-3e6c-438a-ba01-71e9077072fa', 'APPLICATION_BRANDING_PREFERENCES', 'A resource type to keep the application branding preferences'), +('899c69b2-8bf7-46b5-9666-f7f99f90d6cc', 'fido-config', 'A resource type to store FIDO authenticator related preferences'), +('7f24050f-3e3d-4a00-b10f-fd5450d6523e', 'input-validation-configurations', 'A resource type to store input validation related configurations'), +('f4e83b8a-d1c4-a0d6-03a7-d48e268c60c5', 'PK_JWT_CONFIGURATION', 'A resource type to keep the tenant private key jwt configuration.'), +('9ec61e9d-f0e6-4952-9a09-ab842aeb2db2', 'ATTRIBUTE_CONFIGURATION', 'A resource type to store attribute related configurations.'), +('132b0ee6-43e0-462d-8b4b-15b68109d71d', 'ORGANIZATION_CONFIGURATION', 'A resource type to keep the organization configurations.'), +('1fc809a0-dc0d-4cb2-82f3-58934d389236', 'CUSTOM_TEXT', 'A resource type to keep the tenant custom text preferences.'), +('c385a42a-5697-4604-b49a-62456621e926', 'DCR_CONFIGURATION', 'A resource type to keep the DCR configurations.'), +('3e5b1f91-72d8-4fbc-94d1-1b9a4f8c3b07', 'IMPERSONATION_CONFIGURATION', 'A resource type to keep the tenant impersonation preferences.'); + +CREATE TABLE IF NOT EXISTS IDN_CONFIG_RESOURCE ( + ID VARCHAR(255) NOT NULL, + TENANT_ID INT NOT NULL, + NAME VARCHAR(255) NOT NULL, + CREATED_TIME TIMESTAMP NOT NULL, + LAST_MODIFIED TIMESTAMP NOT NULL, + HAS_FILE BOOLEAN NOT NULL, + HAS_ATTRIBUTE BOOLEAN NOT NULL, + TYPE_ID VARCHAR(255) NOT NULL, + UNIQUE (NAME, TENANT_ID, TYPE_ID), + PRIMARY KEY (ID) +); +ALTER TABLE IDN_CONFIG_RESOURCE +ADD CONSTRAINT TYPE_ID_FOREIGN_CONSTRAINT FOREIGN KEY (TYPE_ID) REFERENCES IDN_CONFIG_TYPE (ID) +ON DELETE CASCADE ON UPDATE CASCADE; + +CREATE TABLE IF NOT EXISTS IDN_CONFIG_ATTRIBUTE ( + ID VARCHAR(255) NOT NULL, + RESOURCE_ID VARCHAR(255) NOT NULL, + ATTR_KEY VARCHAR(255) NOT NULL, + ATTR_VALUE VARCHAR(1023) NULL, + PRIMARY KEY (ID), + UNIQUE (RESOURCE_ID, ATTR_KEY) +); +ALTER TABLE IDN_CONFIG_ATTRIBUTE +ADD CONSTRAINT RESOURCE_ID_ATTRIBUTE_FOREIGN_CONSTRAINT FOREIGN KEY (RESOURCE_ID) REFERENCES +IDN_CONFIG_RESOURCE (ID) ON DELETE CASCADE ON UPDATE CASCADE; + +CREATE TABLE IF NOT EXISTS IDN_CONFIG_FILE ( + ID VARCHAR(255) NOT NULL, + `VALUE` BLOB NULL, + RESOURCE_ID VARCHAR(255) NOT NULL, + NAME VARCHAR(255) NULL, + PRIMARY KEY (ID) +); +ALTER TABLE IDN_CONFIG_FILE +ADD CONSTRAINT RESOURCE_ID_FILE_FOREIGN_CONSTRAINT FOREIGN KEY (RESOURCE_ID) REFERENCES +IDN_CONFIG_RESOURCE (ID) ON DELETE CASCADE ON UPDATE CASCADE; + +CREATE TABLE IF NOT EXISTS IDN_REMOTE_FETCH_CONFIG ( + ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + IS_ENABLED CHAR(1) NOT NULL, + REPO_MANAGER_TYPE VARCHAR(255) NOT NULL, + ACTION_LISTENER_TYPE VARCHAR(255) NOT NULL, + CONFIG_DEPLOYER_TYPE VARCHAR(255) NOT NULL, + REMOTE_FETCH_NAME VARCHAR(255), + REMOTE_RESOURCE_URI VARCHAR(255) NOT NULL, + ATTRIBUTES_JSON MEDIUMTEXT NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT UC_REMOTE_RESOURCE_TYPE UNIQUE (TENANT_ID, CONFIG_DEPLOYER_TYPE) +); + +CREATE TABLE IF NOT EXISTS IDN_REMOTE_FETCH_REVISIONS ( + ID VARCHAR(255) NOT NULL, + CONFIG_ID VARCHAR(255) NOT NULL, + FILE_PATH VARCHAR(255) NOT NULL, + FILE_HASH VARCHAR(255), + DEPLOYED_DATE TIMESTAMP, + LAST_SYNC_TIME TIMESTAMP, + DEPLOYMENT_STATUS VARCHAR(255), + ITEM_NAME VARCHAR(255), + DEPLOY_ERR_LOG MEDIUMTEXT, + PRIMARY KEY (ID), + FOREIGN KEY (CONFIG_ID) REFERENCES IDN_REMOTE_FETCH_CONFIG(ID) ON DELETE CASCADE, + CONSTRAINT UC_REVISIONS UNIQUE (CONFIG_ID, ITEM_NAME) +); + + +CREATE TABLE IF NOT EXISTS IDN_USER_FUNCTIONALITY_MAPPING ( + ID VARCHAR(255) NOT NULL, + USER_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + FUNCTIONALITY_ID VARCHAR(255) NOT NULL, + IS_FUNCTIONALITY_LOCKED BOOLEAN NOT NULL, + FUNCTIONALITY_UNLOCK_TIME BIGINT NOT NULL, + FUNCTIONALITY_LOCK_REASON VARCHAR(1023), + FUNCTIONALITY_LOCK_REASON_CODE VARCHAR(255), + PRIMARY KEY (ID), + CONSTRAINT IDN_USER_FUNCTIONALITY_MAPPING_CONSTRAINT UNIQUE (USER_ID, TENANT_ID, FUNCTIONALITY_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_USER_FUNCTIONALITY_PROPERTY ( + ID VARCHAR(255) NOT NULL, + USER_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + FUNCTIONALITY_ID VARCHAR(255) NOT NULL, + PROPERTY_NAME VARCHAR(255), + PROPERTY_VALUE VARCHAR(255), + PRIMARY KEY (ID), + CONSTRAINT IDN_USER_FUNCTIONALITY_PROPERTY_CONSTRAINT UNIQUE (USER_ID, TENANT_ID, FUNCTIONALITY_ID, PROPERTY_NAME) +); + +CREATE TABLE IF NOT EXISTS IDN_CORS_ORIGIN ( + ID INT NOT NULL AUTO_INCREMENT, + TENANT_ID INT NOT NULL, + ORIGIN VARCHAR(2048) NOT NULL, + UUID CHAR(36) NOT NULL, + + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, ORIGIN), + UNIQUE (UUID) +); + +CREATE TABLE IF NOT EXISTS IDN_CORS_ASSOCIATION ( + IDN_CORS_ORIGIN_ID INT NOT NULL, + SP_APP_ID INT NOT NULL, + + PRIMARY KEY (IDN_CORS_ORIGIN_ID, SP_APP_ID), + FOREIGN KEY (IDN_CORS_ORIGIN_ID) REFERENCES IDN_CORS_ORIGIN (ID) ON DELETE CASCADE, + FOREIGN KEY (SP_APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENT ( + ID INTEGER NOT NULL AUTO_INCREMENT, + USER_ID VARCHAR(255) NOT NULL, + APP_ID CHAR(36) NOT NULL, + TENANT_ID INTEGER NOT NULL DEFAULT -1, + CONSENT_ID VARCHAR(255) NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (APP_ID) REFERENCES SP_APP(UUID) ON DELETE CASCADE, + UNIQUE (USER_ID, APP_ID, TENANT_ID), + UNIQUE (CONSENT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_USER_CONSENTED_SCOPES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + CONSENT_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL DEFAULT -1, + SCOPE VARCHAR(255) NOT NULL, + CONSENT BOOLEAN NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (CONSENT_ID) REFERENCES IDN_OAUTH2_USER_CONSENT(CONSENT_ID) ON DELETE CASCADE, + UNIQUE (CONSENT_ID, SCOPE) +); + +CREATE TABLE IF NOT EXISTS IDN_SECRET_TYPE ( + ID VARCHAR(255) NOT NULL, + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(1023) NULL, + PRIMARY KEY (ID), + CONSTRAINT SECRET_TYPE_NAME_CONSTRAINT UNIQUE (NAME) +); + +INSERT INTO IDN_SECRET_TYPE (ID, NAME, DESCRIPTION) VALUES +('1358bdbf-e0cc-4268-a42c-c3e0960e13f0', 'ADAPTIVE_AUTH_CALL_CHOREO', 'Secret type to uniquely identify secrets relevant to callChoreo adaptive auth function'), +('c508ca28-60c0-4493-a758-77e4173ffdb9', 'IDP_SECRET_PROPERTIES', 'Secret type to uniquely identify secrets relevant to identity providers'), +('433df096-62b7-4a36-b3eb-1bed9150ed35', 'IDVP_SECRET_PROPERTIES', 'Secret type to uniquely identify secrets relevant to identity verification providers'), +('29d0c37d-139a-4b1e-a343-7b8d26f0a2a9', 'ANDROID_ATTESTATION_CREDENTIALS', 'Secret type to uniquely identify secrets relevant to android client attestation credentials'), +('33f0a41b-569d-4ea5-a891-6c0e78a1c3b0', 'ACTION_API_ENDPOINT_AUTH_SECRETS', 'Secret type to uniquely identify secrets relevant to action endpoint authentication properties'); + +CREATE TABLE IF NOT EXISTS IDN_SECRET ( + ID VARCHAR(255) NOT NULL, + TENANT_ID INT NOT NULL, + SECRET_NAME VARCHAR(1023) NOT NULL, + SECRET_VALUE VARCHAR(8000) NOT NULL, + CREATED_TIME TIMESTAMP NOT NULL, + LAST_MODIFIED TIMESTAMP NOT NULL, + TYPE_ID VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(1023) NULL, + KEY_ID VARCHAR(255) NULL, + PRIMARY KEY (ID), + FOREIGN KEY (TYPE_ID) REFERENCES IDN_SECRET_TYPE(ID) ON DELETE CASCADE, + UNIQUE (SECRET_NAME, TENANT_ID, TYPE_ID) +); + +CREATE TABLE IF NOT EXISTS SP_SHARED_APP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + MAIN_APP_ID CHAR(36) NOT NULL, + OWNER_ORG_ID CHAR(36) NOT NULL, + SHARED_APP_ID CHAR(36) NOT NULL, + SHARED_ORG_ID CHAR(36) NOT NULL, + SHARE_WITH_ALL_CHILDREN BOOLEAN DEFAULT FALSE, + PRIMARY KEY (ID), + FOREIGN KEY (MAIN_APP_ID) REFERENCES SP_APP(UUID) ON DELETE CASCADE, + FOREIGN KEY (SHARED_APP_ID) REFERENCES SP_APP(UUID) ON DELETE CASCADE, + UNIQUE (MAIN_APP_ID, OWNER_ORG_ID, SHARED_ORG_ID), + UNIQUE (SHARED_APP_ID) +); + +CREATE TABLE IF NOT EXISTS IDVP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + UUID CHAR(36) NOT NULL, + TENANT_ID INTEGER NOT NULL, + IDVP_TYPE VARCHAR(254), + NAME VARCHAR(254), + DESCRIPTION VARCHAR(1024), + IS_ENABLED CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, NAME), + UNIQUE (UUID) +); + +CREATE TABLE IF NOT EXISTS IDVP_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + IDVP_ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + CLAIM VARCHAR(254), + LOCAL_CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDVP_ID, CLAIM, TENANT_ID), + FOREIGN KEY (IDVP_ID) REFERENCES IDVP(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDVP_CONFIG ( + ID INTEGER NOT NULL AUTO_INCREMENT, + IDVP_ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + PROPERTY_KEY VARCHAR(254) NOT NULL, + PROPERTY_VALUE VARCHAR(1024), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDVP_ID, PROPERTY_KEY, TENANT_ID), + FOREIGN KEY (IDVP_ID) REFERENCES IDVP(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDV_CLAIM ( + ID INTEGER NOT NULL AUTO_INCREMENT, + UUID CHAR(36) NOT NULL, + USER_ID VARCHAR(254) NOT NULL, + CLAIM_URI VARCHAR(254), + IDVP_ID CHAR(36) NOT NULL, + TENANT_ID INTEGER NOT NULL, + IS_VERIFIED CHAR(1) NOT NULL DEFAULT '0', + METADATA BLOB, + PRIMARY KEY (ID), + UNIQUE (CLAIM_URI, TENANT_ID, USER_ID, IDVP_ID), + UNIQUE (UUID), + FOREIGN KEY (IDVP_ID) REFERENCES IDVP(UUID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR ( + REQ_URI_REF VARCHAR(255) PRIMARY KEY, + CLIENT_ID VARCHAR(255) NOT NULL, + SCHEDULED_EXPIRY BIGINT NOT NULL, + PARAMETERS MEDIUMTEXT +); + +CREATE TABLE IF NOT EXISTS IDN_ORG_USER_INVITATION ( + ID INTEGER NOT NULL AUTO_INCREMENT, + INVITATION_ID VARCHAR(40) NOT NULL, + CONFIRMATION_CODE VARCHAR(40) NOT NULL, + USER_NAME VARCHAR(254) NOT NULL, + DOMAIN_NAME VARCHAR(254) NOT NULL, + EMAIL VARCHAR(254) NOT NULL, + USER_ORG_ID VARCHAR(254) NOT NULL, + INVITED_ORG_ID VARCHAR(254) NOT NULL, + USER_REDIRECT_URL VARCHAR(1024) NOT NULL, + STATUS VARCHAR(10) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + EXPIRED_AT TIMESTAMP NOT NULL, + PRIMARY KEY (INVITATION_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_ORG_USER_INVITE_ASSIGNMENT( + ID INTEGER NOT NULL AUTO_INCREMENT, + INVITATION_ID VARCHAR(40) NOT NULL, + ASSIGNMENT_ID VARCHAR(255) NOT NULL, + ASSIGNMENT_TYPE VARCHAR(255) NOT NULL, + PRIMARY KEY (INVITATION_ID, ASSIGNMENT_ID, ASSIGNMENT_TYPE), + FOREIGN KEY (INVITATION_ID) REFERENCES IDN_ORG_USER_INVITATION(INVITATION_ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS API_RESOURCE ( + ID CHAR(36) NOT NULL PRIMARY KEY, + CURSOR_KEY INTEGER NOT NULL AUTO_INCREMENT, + NAME VARCHAR(255) NOT NULL, + IDENTIFIER VARCHAR(255) NOT NULL, + TENANT_ID INT, + DESCRIPTION VARCHAR(255), + TYPE VARCHAR(255) NOT NULL, + REQUIRES_AUTHORIZATION BOOLEAN NOT NULL +); + +CREATE TABLE IF NOT EXISTS API_RESOURCE_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + API_ID CHAR(36) NOT NULL, + NAME VARCHAR(255) NOT NULL, + `VALUE` VARCHAR(255) NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT API_RESOURCE_PROPERTY_CONSTRAINT UNIQUE (API_ID, NAME), + FOREIGN KEY (API_ID) REFERENCES API_RESOURCE(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS SCOPE ( + ID CHAR(36) NOT NULL PRIMARY KEY, + CURSOR_KEY INTEGER NOT NULL AUTO_INCREMENT, + API_ID CHAR(36) NOT NULL, + NAME VARCHAR(255) NOT NULL, + DISPLAY_NAME VARCHAR(255) NOT NULL, + TENANT_ID INT, + DESCRIPTION VARCHAR(300), + FOREIGN KEY (API_ID) REFERENCES API_RESOURCE(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS APP_ROLE_ASSOCIATION ( + APP_ID CHAR(36) NOT NULL, + ROLE_ID VARCHAR(255) NOT NULL, + PRIMARY KEY (APP_ID, ROLE_ID), + FOREIGN KEY (APP_ID) REFERENCES SP_APP(UUID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS ROLE_SCOPE ( + ROLE_ID VARCHAR(255) NOT NULL, + SCOPE_ID CHAR(36) NOT NULL, + PRIMARY KEY (ROLE_ID, SCOPE_ID), + FOREIGN KEY (SCOPE_ID) REFERENCES SCOPE(ID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS AUTHORIZED_API( + APP_ID CHAR(36) NOT NULL, + API_ID CHAR(36) NOT NULL, + POLICY_ID VARCHAR(255) NOT NULL, + CONSTRAINT PK_APP_API PRIMARY KEY (APP_ID, API_ID), + FOREIGN KEY (API_ID) REFERENCES API_RESOURCE(ID) ON DELETE CASCADE, + FOREIGN KEY (APP_ID) REFERENCES SP_APP(UUID) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS AUTHORIZED_SCOPE( + APP_ID CHAR(36) NOT NULL, + API_ID CHAR(36) NOT NULL, + SCOPE_ID CHAR(36) NOT NULL, + CONSTRAINT PK_APP_API_SCOPE PRIMARY KEY (APP_ID, API_ID, SCOPE_ID), + FOREIGN KEY (API_ID) REFERENCES API_RESOURCE(ID), + FOREIGN KEY (SCOPE_ID) REFERENCES SCOPE(ID) ON DELETE CASCADE, + FOREIGN KEY (APP_ID) REFERENCES SP_APP(UUID), + FOREIGN KEY (APP_ID, API_ID) REFERENCES AUTHORIZED_API(APP_ID, API_ID) ON DELETE CASCADE, + CONSTRAINT AUTHORIZED_SCOPE_UNIQUE UNIQUE (APP_ID, SCOPE_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_TYPE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TYPE_KEY VARCHAR(255) NOT NULL, + NAME VARCHAR(255) NOT NULL, + CHANNEL VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), + CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_ORG_TEMPLATE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TEMPLATE_KEY VARCHAR(50) NOT NULL, + LOCALE VARCHAR(50) NOT NULL, + SUBJECT VARCHAR(4000), + BODY MEDIUMTEXT, + FOOTER MEDIUMTEXT, + CONTENT_TYPE VARCHAR(50), + TYPE_ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, + CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), + CONSTRAINT ORG_NOTIFICATION_TEMPLATE_LOCALE_CONSTRAINT UNIQUE (LOCALE, TYPE_ID, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_APP_TEMPLATE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TEMPLATE_KEY VARCHAR(50) NOT NULL, + LOCALE VARCHAR(50) NOT NULL, + SUBJECT VARCHAR(4000), + BODY MEDIUMTEXT, + FOOTER MEDIUMTEXT, + CONTENT_TYPE VARCHAR(50), + TYPE_ID INTEGER NOT NULL, + APP_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, + CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), + CONSTRAINT APP_NOTIFICATION_TEMPLATE_LOCALE_CONSTRAINT UNIQUE (LOCALE, TYPE_ID, APP_ID, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_ACTION ( + UUID CHAR(36) NOT NULL, + TYPE VARCHAR(50) NOT NULL, + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(255), + STATUS VARCHAR(10) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (UUID) +); + +CREATE TABLE IF NOT EXISTS IDN_ACTION_ENDPOINT ( + ACTION_UUID CHAR(36) NOT NULL, + PROPERTY_NAME VARCHAR(100) NOT NULL, + PROPERTY_VALUE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ACTION_UUID, PROPERTY_NAME), + FOREIGN KEY (ACTION_UUID) REFERENCES IDN_ACTION(UUID) ON DELETE CASCADE +); + +-- --------------------------- INDEX CREATION ----------------------------- +-- IDN_OAUTH2_ACCESS_TOKEN -- +CREATE INDEX IDX_TC ON IDN_OAUTH2_ACCESS_TOKEN(TIME_CREATED); +CREATE INDEX IDX_ATH ON IDN_OAUTH2_ACCESS_TOKEN(ACCESS_TOKEN_HASH); +CREATE INDEX IDX_AT_TI_UD ON IDN_OAUTH2_ACCESS_TOKEN(AUTHZ_USER, TENANT_ID, TOKEN_STATE, USER_DOMAIN); +CREATE INDEX IDX_AT_AT ON IDN_OAUTH2_ACCESS_TOKEN(ACCESS_TOKEN); +CREATE INDEX IDX_AT_RTH ON IDN_OAUTH2_ACCESS_TOKEN(REFRESH_TOKEN_HASH); +CREATE INDEX IDX_AT_RT ON IDN_OAUTH2_ACCESS_TOKEN(REFRESH_TOKEN); +CREATE INDEX IDX_TBR_TS ON IDN_OAUTH2_ACCESS_TOKEN(TOKEN_BINDING_REF, TOKEN_STATE); + +-- IDN_OAUTH2_AUTHORIZATION_CODE -- +CREATE INDEX IDX_AUTHORIZATION_CODE_HASH ON IDN_OAUTH2_AUTHORIZATION_CODE (AUTHORIZATION_CODE_HASH, CONSUMER_KEY_ID); +CREATE INDEX IDX_AUTHORIZATION_CODE_AU_TI ON IDN_OAUTH2_AUTHORIZATION_CODE (AUTHZ_USER, TENANT_ID, USER_DOMAIN, STATE); +CREATE INDEX IDX_AC_CKID ON IDN_OAUTH2_AUTHORIZATION_CODE(CONSUMER_KEY_ID); +CREATE INDEX IDX_AC_TID ON IDN_OAUTH2_AUTHORIZATION_CODE(TOKEN_ID); +CREATE INDEX IDX_AC_AC_CKID ON IDN_OAUTH2_AUTHORIZATION_CODE(AUTHORIZATION_CODE, CONSUMER_KEY_ID); +CREATE INDEX IDX_AT_CKID_AU_TID_UD_TSH_TS ON IDN_OAUTH2_ACCESS_TOKEN(CONSUMER_KEY_ID, AUTHZ_USER, TENANT_ID, USER_DOMAIN, TOKEN_SCOPE_HASH, TOKEN_STATE); + +-- IDN_SCIM_GROUP -- +CREATE INDEX IDX_IDN_SCIM_GROUP_TI_RN ON IDN_SCIM_GROUP (TENANT_ID, ROLE_NAME); +CREATE INDEX IDX_IDN_SCIM_GROUP_TI_RN_AN ON IDN_SCIM_GROUP (TENANT_ID, ROLE_NAME, ATTR_NAME); + +-- IDN_AUTH_SESSION_STORE -- +CREATE INDEX IDX_IDN_AUTH_SESSION_TIME ON IDN_AUTH_SESSION_STORE (TIME_CREATED); +CREATE INDEX IDX_IDN_AUTH_SSTR_ST_OP_ID_TM ON IDN_AUTH_SESSION_STORE (OPERATION, SESSION_TYPE, SESSION_ID, TIME_CREATED); +CREATE INDEX IDX_IDN_AUTH_SSTR_ET_ID ON IDN_AUTH_SESSION_STORE (EXPIRY_TIME, SESSION_ID); + +-- IDN_AUTH_TEMP_SESSION_STORE -- +CREATE INDEX IDX_IDN_AUTH_TMP_SESSION_TIME ON IDN_AUTH_TEMP_SESSION_STORE (TIME_CREATED); + +-- IDN_OIDC_SCOPE_CLAIM_MAPPING -- +CREATE INDEX IDX_AT_SI_ECI ON IDN_OIDC_SCOPE_CLAIM_MAPPING(SCOPE_ID, EXTERNAL_CLAIM_ID); + +-- IDN_OAUTH2_SCOPE -- +CREATE INDEX IDX_SC_TID ON IDN_OAUTH2_SCOPE(TENANT_ID); + +-- IDN_OAUTH2_SCOPE_BINDING -- +CREATE INDEX IDX_SB_SCPID ON IDN_OAUTH2_SCOPE_BINDING(SCOPE_ID); + +-- IDN_OIDC_REQ_OBJECT_REFERENCE -- +CREATE INDEX IDX_OROR_TID ON IDN_OIDC_REQ_OBJECT_REFERENCE(TOKEN_ID); + +-- IDN_OAUTH2_ACCESS_TOKEN_SCOPE -- +CREATE INDEX IDX_ATS_TID ON IDN_OAUTH2_ACCESS_TOKEN_SCOPE(TOKEN_ID); + +-- SP_TEMPLATE -- +CREATE INDEX IDX_SP_TEMPLATE ON SP_TEMPLATE (TENANT_ID, NAME); + +-- IDN_AUTH_USER -- +CREATE INDEX IDX_AUTH_USER_UN_TID_DN ON IDN_AUTH_USER (USER_NAME, TENANT_ID, DOMAIN_NAME); +CREATE INDEX IDX_AUTH_USER_DN_TOD ON IDN_AUTH_USER (DOMAIN_NAME, TENANT_ID); + +-- IDN_AUTH_USER_SESSION_MAPPING -- +CREATE INDEX IDX_USER_ID ON IDN_AUTH_USER_SESSION_MAPPING (USER_ID); +CREATE INDEX IDX_SESSION_ID ON IDN_AUTH_USER_SESSION_MAPPING (SESSION_ID); + +-- IDN_AUTH_SESSION_APP_INFO -- +CREATE INDEX IDX_AUTH_SAI_UN_AID_SID ON IDN_AUTH_SESSION_APP_INFO (APP_ID, SUBJECT, SESSION_ID); + +-- IDN_OAUTH_CONSUMER_APPS -- +CREATE INDEX IDX_OCA_UM_TID_UD_APN ON IDN_OAUTH_CONSUMER_APPS(USERNAME,TENANT_ID,USER_DOMAIN, APP_NAME); + +-- IDX_SPI_APP -- +CREATE INDEX IDX_SPI_APP ON SP_INBOUND_AUTH(APP_ID); + +-- IDN_OIDC_PROPERTY -- +CREATE INDEX IDX_IOP_CK ON IDN_OIDC_PROPERTY(TENANT_ID, CONSUMER_KEY); + +-- IDN_FIDO2_PROPERTY -- +CREATE INDEX IDX_FIDO2_STR ON FIDO2_DEVICE_STORE(USER_NAME, TENANT_ID, DOMAIN_NAME, CREDENTIAL_ID, USER_HANDLE); + +-- IDN_ASSOCIATED_ID -- +CREATE INDEX IDX_AI_DN_UN_AI ON IDN_ASSOCIATED_ID(DOMAIN_NAME, USER_NAME, ASSOCIATION_ID); + +-- IDN_OAUTH2_TOKEN_BINDING -- +CREATE INDEX IDX_IDN_AUTH_BIND ON IDN_OAUTH2_TOKEN_BINDING (TOKEN_BINDING_REF); +CREATE INDEX IDX_TK_VALUE_TYPE ON IDN_OAUTH2_TOKEN_BINDING (TOKEN_BINDING_VALUE, TOKEN_BINDING_TYPE); + +-- IDN_FED_AUTH_SESSION_MAPPING -- +CREATE INDEX IDX_FEDERATED_AUTH_SESSION_ID ON IDN_FED_AUTH_SESSION_MAPPING (SESSION_ID); + +-- IDN_REMOTE_FETCH_REVISIONS -- +CREATE INDEX IDX_REMOTE_FETCH_REVISION_CONFIG_ID ON IDN_REMOTE_FETCH_REVISIONS (CONFIG_ID); + +-- IDN_CORS_ASSOCIATION -- +CREATE INDEX IDX_CORS_SP_APP_ID ON IDN_CORS_ASSOCIATION (SP_APP_ID); + +-- IDN_CORS_ASSOCIATION -- +CREATE INDEX IDX_CORS_ORIGIN_ID ON IDN_CORS_ASSOCIATION (IDN_CORS_ORIGIN_ID); + +-- IDN_SECRET -- +CREATE INDEX IDN_SECRET_TYPE_ID ON IDN_SECRET (TYPE_ID); + +-- IDN_CLAIM -- +CREATE INDEX IDX_CLAIM_TI_CU ON IDN_CLAIM (TENANT_ID, CLAIM_URI); + +-- IDP_AUTHENTICATOR_PROPERTY -- +CREATE INDEX IDX_AUTH_PROP_AUTH_ID ON IDP_AUTHENTICATOR_PROPERTY (AUTHENTICATOR_ID); + +-- IDN_CONFIG_FILE -- +CREATE INDEX IDX_CON_FILE_RES_ID ON IDN_CONFIG_FILE (RESOURCE_ID); + +-- SCOPE -- +CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); + +-- ACTIONS -- +CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/repository/conf/carbon.xml b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/repository/conf/carbon.xml new file mode 100644 index 000000000000..a5a1a6470cbc --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/repository/conf/carbon.xml @@ -0,0 +1,686 @@ + + + + + + + + WSO2 Identity Server + + + IS + + + 5.3.0 + + + localhost + + + localhost + + + local:/${carbon.context}/services/ + + + + + + + IdentityServer + + + + + + + org.wso2.carbon + + + / + + + + + + + + + 15 + + + + + + + + + 0 + + + + + 9999 + + 11111 + + + + + + 10389 + + 8000 + + + + + + 10500 + + + + + + + + + org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory + + + + + + + + + java + + + + + + + + + + false + + + false + + + 600 + + + + false + + + + + + + + 30 + + + + + + + + + 15 + + + + + + ${carbon.home}/repository/deployment/server/ + + + 15 + + + ${carbon.home}/repository/conf/axis2/axis2.xml + + + 30000 + + + ${carbon.home}/repository/deployment/client/ + + ${carbon.home}/repository/conf/axis2/axis2_client.xml + + true + + + + + + + + + + admin + Default Administrator Role + + + user + Default User Role + + + + + + + + + + + + ${carbon.home}/repository/resources/security/wso2carbon.jks + + JKS + + wso2carbon + + wso2carbon + + wso2carbon + + + + + + ${carbon.home}/repository/resources/security/client-truststore.jks + + JKS + + wso2carbon + + + + + + + + + + + + + + + + + + + UserManager + + + false + + org.wso2.carbon.identity.provider.AttributeCallbackHandler + + + org.wso2.carbon.identity.sts.store.DBTokenStore + + + true + allow + + + + + + + claim_mgt_menu + identity_mgt_emailtemplate_menu + identity_security_questions_menu + + + + ${carbon.home}/tmp/work + + + + + + true + + + 10 + + + 30 + + + + + + 100 + + + + keystore + certificate + * + + org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor + + + + + jarZip + + org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor + + + + dbs + + org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor + + + + tools + + org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor + + + + toolsAny + + org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor + + + + + + + + + + info + org.wso2.carbon.core.transports.util.InfoProcessor + + + wsdl + org.wso2.carbon.core.transports.util.Wsdl11Processor + + + wsdl2 + org.wso2.carbon.core.transports.util.Wsdl20Processor + + + xsd + org.wso2.carbon.core.transports.util.XsdProcessor + + + + + + false + false + true + svn + http://svnrepo.example.com/repos/ + username + password + true + + + + + + + + + + + + + + + ${require.carbon.servlet} + + + + + true + + + + + + + default repository + http://product-dist.wso2.com/p2/carbon/releases/wilkes/ + + + + + + + + true + + + + + + true + + diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/repository/conf/identity/identity.xml b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/repository/conf/identity/identity.xml new file mode 100644 index 000000000000..07de6831dbf4 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/repository/conf/identity/identity.xml @@ -0,0 +1,743 @@ + + + + + + + + + jdbc/WSO2IdentityDB + + + + + true + true + 0 + + true + 20160 + 1140 + + + true + 720 + + + + + + + 15 + 20160 + + + + + + ${carbon.home}/conf/keystores + SunX509 + SunX509 + + + + SelfAndManaged + CertValidate + + + + + + + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/openidserver + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/openid + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/openid_login.do + + + false + + 7200 + + false + + + + + + + + + + + + + + + + + + + + + + -1 + -1 + -1 + -1 + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/request-token + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/authorize-url + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/access-token + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/authorize + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/revoke + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/introspect + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/userinfo + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oidc/checksession + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oidc/logout + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_authz.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_error.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_consent.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_logout_consent.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_logout.do + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/.well-known/webfinger + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/identity/connect/register + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/jwks + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/oidcdiscovery + + + 300 + + 3600 + + 3600 + + 84600 + + 300 + + false + + true + + org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor + + + + false + + + + + + token + org.wso2.carbon.identity.oauth2.authz.handlers.AccessTokenResponseTypeHandler + + + code + org.wso2.carbon.identity.oauth2.authz.handlers.CodeResponseTypeHandler + + + id_token + org.wso2.carbon.identity.oauth2.authz.handlers.IDTokenResponseTypeHandler + + + id_token token + org.wso2.carbon.identity.oauth2.authz.handlers.IDTokenTokenResponseTypeHandler + + + + + + authorization_code + org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationCodeGrantHandler + + + password + org.wso2.carbon.identity.oauth2.token.handlers.grant.PasswordGrantHandler + + + refresh_token + org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler + + + client_credentials + org.wso2.carbon.identity.oauth2.token.handlers.grant.ClientCredentialsGrantHandler + + + urn:ietf:params:oauth:grant-type:saml2-bearer + org.wso2.carbon.identity.oauth2.token.handlers.grant.saml.SAML2BearerGrantHandler + + + iwa:ntlm + org.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm.NTLMAuthenticationGrantHandler + + + idTokenNotAllowedGrantType + org.wso2.carbon.identity.oauth2.token.handlers.grant.idTokenNotAllowedGrantHandler + false + + + + + + + + + false + + + + false + + + + false + org.wso2.carbon.identity.oauth2.authcontext.JWTTokenGenerator + org.wso2.carbon.identity.oauth2.authcontext.DefaultClaimsRetriever + http://wso2.org/claims + SHA256withRSA + 10 + + + + + + org.wso2.carbon.identity.openidconnect.DefaultIDTokenBuilder + SHA256withRSA + + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token + org.wso2.carbon.identity.openidconnect.DefaultOIDCClaimsCallbackHandler + 3600 + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoUserStoreClaimRetriever + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInforRequestDefaultValidator + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoISAccessTokenValidator + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoJSONResponseBuilder + false + + + + + + + + gtalk + talk.google.com + 5222 + gmail.com + multifactor1@gmail.com + wso2carbon + + + + + + 157680000 + 157680000 + ${carbon.host} + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/samlsso + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/samlsso_logout.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/samlsso_notification.do + 5 + 60000 + + false + http://wso2.org/claims + org.wso2.carbon.identity.sso.saml.builders.assertion.ExtendedDefaultAssertionBuilder + + org.wso2.carbon.identity.sso.saml.builders.encryption.DefaultSSOEncrypter + org.wso2.carbon.identity.sso.saml.builders.signature.DefaultSSOSigner + org.wso2.carbon.identity.sso.saml.validators.SAML2HTTPRedirectDeflateSignatureValidator + + + + 5 + false + http://www.w3.org/2000/09/xmldsig#rsa-sha1 + http://www.w3.org/2000/09/xmldsig#sha1 + true + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/services/wso2carbon-sts + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/passivests + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/retry.do + org.wso2.carbon.identity.sts.passive.utils.NoPersistenceTokenStore + true + + + + + false + ${Ports.ThriftEntitlementReceivePort} + 10000 + + ${carbon.home}/repository/resources/security/wso2carbon.jks + wso2carbon + + + ${carbon.host} + + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2/scim/Users + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2/scim/Groups + + + 5 + + + 10 + local://services + + + + + + + + + + + + + org.wso2.carbon.identity.governance.store.JDBCIdentityDataStore + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /permission/admin/manage/identity/identitymgt + + + + + + /permission/admin/manage/identity/usermgt/view + + + /permission/admin/manage/identity/usermgt/view + + + + /permission/admin/manage/identity/configmgt/list + + + + /permission/admin/manage/identity/configmgt/add + + + /permission/admin/manage/identity/configmgt/update + + + + /permission/admin/manage/identity/configmgt/delete + + + + /permission/admin/manage/identity/configmgt/add + + + /permission/admin/manage/identity/configmgt/update + + + + /permission/admin/manage/identity/configmgt/delete + + + + /permission/admin/manage/identity/configmgt/add + + + /permission/admin/manage/identity/configmgt/update + + + + /permission/admin/manage/identity/configmgt/delete + + + + + + + /permission/admin/manage/identity/consentmgt/add + + + + /permission/admin/manage/identity/consentmgt/delete + + + + /permission/admin/manage/identity/consentmgt/add + + + + /permission/admin/manage/identity/consentmgt/delete + + + + /permission/admin/manage/identity/consentmgt/add + + + + /permission/admin/manage/identity/consentmgt/delete + + + + /permission/admin/manage/identity/identitymgt + + + + /permission/admin/manage/identity/applicationmgt/create + + + /permission/admin/manage/identity/applicationmgt/delete + + + /permission/admin/manage/identity/applicationmgt/update + + + /permission/admin/manage/identity/applicationmgt/view + + + /permission/admin/manage/identity/applicationmgt/delete + + + /permission/admin/manage/identity/applicationmgt/create + + + /permission/admin/manage/identity/applicationmgt/view + + + /permission/admin/manage/identity/pep + + + /permission/admin/manage/identity/usermgt/create + + + /permission/admin/manage/identity/usermgt/list + + + /permission/admin/manage/identity/rolemgt/create + + + /permission/admin/manage/identity/rolemgt/view + + + /permission/admin/manage/identity/usermgt/view + + + /permission/admin/manage/identity/usermgt/update + + + /permission/admin/manage/identity/usermgt/update + + + /permission/admin/manage/identity/usermgt/delete + + + /permission/admin/manage/identity/rolemgt/view + + + /permission/admin/manage/identity/rolemgt/update + + + /permission/admin/manage/identity/rolemgt/update + + + /permission/admin/manage/identity/rolemgt/delete + + + /permission/admin/login + + + /permission/admin/manage/identity/usermgt/delete + + + /permission/admin/login + + + /permission/admin/login + + + /permission/admin/manage/identity/usermgt/create + + + + + + + + + /permission/admin/manage/identity/usermgt + + + /permission/admin/manage/identity/applicationmgt + + + + + + + /permission/admin/manage/identity/usermgt/update + + + + + + /permission/admin/manage/humantask/viewtasks + + + /permission/admin/login + + + /permission/admin/manage/identity/usermgt + + + /permission/admin/manage/identity/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /api/identity/user/v0.9 + /api/identity/recovery/v0.9 + /oauth2 + /api/identity/entitlement + + + /identity/(.*) + + + + + + applications,connections + + + + 300 + diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/testng.xml b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/testng.xml index 917b616e3e8a..5e099dcc02ab 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/testng.xml +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/test/resources/testng.xml @@ -17,11 +17,13 @@ - + + + diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt.ui/pom.xml b/components/application-mgt/org.wso2.carbon.identity.application.mgt.ui/pom.xml index 9218e51bb16c..da3a54c9c475 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt.ui/pom.xml +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt.ui/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework application-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml b/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml index 94e6f39855a6..15a205697dc2 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework application-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml org.wso2.carbon.identity.application.mgt diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java index dc21ae0e51cf..a9d3b9d4127f 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java @@ -3631,31 +3631,32 @@ private SpTrustedAppMetadata getSpTrustedAppMetadata(int applicationId, Connecti loadAppConfigs.setInt(2, tenantID); try (ResultSet appConfigResultSet = loadAppConfigs.executeQuery()) { - if (appConfigResultSet.isBeforeFirst()) { - spTrustedAppMetadata = new SpTrustedAppMetadata(); - + while (appConfigResultSet.next()) { + if (spTrustedAppMetadata == null) { + spTrustedAppMetadata = new SpTrustedAppMetadata(); + } // There should be maximum two entries for each service provider. One for Android and one for iOS. - while (appConfigResultSet.next()) { - PlatformType platformType = PlatformType.valueOf(appConfigResultSet.getString(1)); - if (PlatformType.ANDROID.equals(platformType)) { - spTrustedAppMetadata.setAndroidPackageName(appConfigResultSet.getString(2)); - if (appConfigResultSet.getString(3) != null) { - spTrustedAppMetadata.setAndroidThumbprints( - appConfigResultSet.getString(3).split(ATTRIBUTE_SEPARATOR)); - } else { - spTrustedAppMetadata.setAndroidThumbprints(new String[0]); - } - } else if (PlatformType.IOS.equals(platformType)) { - spTrustedAppMetadata.setAppleAppId(appConfigResultSet.getString(2)); + PlatformType platformType = PlatformType.valueOf(appConfigResultSet.getString(1)); + if (PlatformType.ANDROID.equals(platformType)) { + spTrustedAppMetadata.setAndroidPackageName(appConfigResultSet.getString(2)); + if (appConfigResultSet.getString(3) != null) { + spTrustedAppMetadata.setAndroidThumbprints( + appConfigResultSet.getString(3).split(ATTRIBUTE_SEPARATOR)); + } else { + spTrustedAppMetadata.setAndroidThumbprints(new String[0]); } - spTrustedAppMetadata.setIsFidoTrusted(appConfigResultSet.getBoolean(4)); + } else if (PlatformType.IOS.equals(platformType)) { + spTrustedAppMetadata.setAppleAppId(appConfigResultSet.getString(2)); } - + spTrustedAppMetadata.setIsFidoTrusted(appConfigResultSet.getBoolean(4)); + } + if (spTrustedAppMetadata != null) { // If consent required property is disabled, consent is always considered as granted. spTrustedAppMetadata.setIsConsentGranted(!ApplicationMgtUtil.isTrustedAppConsentRequired() || getTrustedAppConsent(spPropertyList)); } } + } catch (SQLException e) { throw new IdentityApplicationManagementException("Error while retrieving trusted app configurations.", e); } diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java index 7e0a21053f57..75131ab0ba3a 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java @@ -437,9 +437,9 @@ public class ApplicationMgtDBQueries { public static final String LOAD_DISCOVERABLE_APPS_BY_TENANT_ORACLE = "SELECT ID, APP_NAME, VERSION, " + "DESCRIPTION, UUID, IMAGE_URL, ACCESS_URL, USERNAME, USER_STORE, TENANT_ID FROM " + - "(SELECT ID, APP_NAME, DESCRIPTION, UUID, IMAGE_URL, ACCESS_URL, USERNAME, USER_STORE, TENANT_ID, rownum " + - "AS rnum FROM " + - "(SELECT ID, APP_NAME, DESCRIPTION, UUID, IMAGE_URL, ACCESS_URL, USERNAME, USER_STORE, " + + "(SELECT ID, APP_NAME, VERSION, DESCRIPTION, UUID, IMAGE_URL, ACCESS_URL, USERNAME, USER_STORE, TENANT_ID" + + ", rownum AS rnum FROM " + + "(SELECT ID, APP_NAME, VERSION, DESCRIPTION, UUID, IMAGE_URL, ACCESS_URL, USERNAME, USER_STORE, " + "TENANT_ID, IS_DISCOVERABLE FROM SP_APP ORDER BY ID DESC) WHERE TENANT_ID = :TENANT_ID; AND " + "rownum <= :END_INDEX; AND IS_DISCOVERABLE = '1') WHERE rnum > :ZERO_BASED_START_INDEX;"; diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/DefaultRoleManagementListener.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/DefaultRoleManagementListener.java index 58a1976827c7..cdf9a56df19e 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/DefaultRoleManagementListener.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/DefaultRoleManagementListener.java @@ -24,6 +24,7 @@ import org.wso2.carbon.identity.application.common.model.ApplicationBasicInfo; import org.wso2.carbon.identity.application.common.model.AuthorizedScopes; import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.ApplicationConstants; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementService; import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementServiceImpl; @@ -34,6 +35,7 @@ import org.wso2.carbon.identity.application.mgt.internal.cache.ServiceProviderByResourceIdCache; import org.wso2.carbon.identity.application.mgt.internal.cache.ServiceProviderIDCacheKey; import org.wso2.carbon.identity.application.mgt.internal.cache.ServiceProviderResourceIdCacheKey; +import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementClientException; import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementServerException; @@ -65,9 +67,6 @@ */ public class DefaultRoleManagementListener extends AbstractApplicationMgtListener implements RoleManagementListener { - private static final AuthorizedAPIManagementService authorizedAPIManagementService = - new AuthorizedAPIManagementServiceImpl(); - @Override public int getExecutionOrderId() { @@ -92,7 +91,7 @@ public void preAddRole(String roleName, List userList, List grou throws IdentityRoleManagementException { if (APPLICATION.equalsIgnoreCase(audience)) { - validateApplicationRoleAudience(audienceId, tenantDomain); + validateApplicationTypeAndRoleAudience(audienceId, tenantDomain); validatePermissionsForApplication(permissions, audienceId, tenantDomain); } } @@ -513,13 +512,14 @@ public void postGetAssociatedApplicationIdsByRoleId(List associatedAppli } /** - * Validate application role audience. + * Validate application type and the role audience of the application. The application type will be set to the + * thread local properties. * * @param applicationId Application ID. * @param tenantDomain Tenant domain. * @throws IdentityRoleManagementException Error occurred while validating application role audience. */ - private void validateApplicationRoleAudience(String applicationId, String tenantDomain) + private void validateApplicationTypeAndRoleAudience(String applicationId, String tenantDomain) throws IdentityRoleManagementException { try { @@ -536,6 +536,17 @@ private void validateApplicationRoleAudience(String applicationId, String tenant throw new IdentityRoleManagementClientException(INVALID_AUDIENCE.getCode(), "Application: " + applicationId + " does not have Application role audience type"); } + + // Set thread local property to identify that the application is a fragment application. This property + // will be used in the role management component to identify the application type. + if (IdentityUtil.threadLocalProperties.get().get(ApplicationConstants.IS_FRAGMENT_APP) != null) { + IdentityUtil.threadLocalProperties.get().remove(ApplicationConstants.IS_FRAGMENT_APP); + } + if (app.getSpProperties() != null && Arrays.stream(app.getSpProperties()) + .anyMatch(property -> ApplicationConstants.IS_FRAGMENT_APP.equals(property.getName()) + && Boolean.parseBoolean(property.getValue()))) { + IdentityUtil.threadLocalProperties.get().put(ApplicationConstants.IS_FRAGMENT_APP, Boolean.TRUE); + } } catch (IdentityApplicationManagementException e) { String errorMessage = "Error while retrieving the application for the given id: " + applicationId; throw new IdentityRoleManagementServerException(UNEXPECTED_SERVER_ERROR.getCode(), errorMessage, e); @@ -579,6 +590,7 @@ private List getAuthorizedScopes(String appId, String tenantDomain) List authorizedScopesList; try { + AuthorizedAPIManagementService authorizedAPIManagementService = new AuthorizedAPIManagementServiceImpl(); authorizedScopesList = authorizedAPIManagementService.getAuthorizedScopes(appId, tenantDomain); } catch (IdentityApplicationManagementException e) { throw new IdentityRoleManagementException("Error while retrieving authorized scopes.", diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/DefaultRoleManagementListenerTest.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/DefaultRoleManagementListenerTest.java new file mode 100644 index 000000000000..3160d5a9b3ea --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/DefaultRoleManagementListenerTest.java @@ -0,0 +1,268 @@ +/* + * 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.mgt; + +import org.mockito.MockedStatic; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.common.model.ServiceProviderProperty; +import org.wso2.carbon.identity.application.mgt.listener.DefaultRoleManagementListener; +import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementClientException; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementServerException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/** + * Contains the unit tests for the default role management listener. + */ +public class DefaultRoleManagementListenerTest { + + private DefaultRoleManagementListener defaultRoleManagementListener; + private static final String ROLE_NAME = "test_role"; + private static final String APPLICATION_NAME = "app_name"; + private static final String APPLICATION_RES_ID = "app_id"; + private static final String IS_FRAGMENT_APP = "isFragmentApp"; + private static final String APPLICATION_AUD = "APPLICATION"; + private static final String ORGANIZATION_AUD = "ORGANIZATION"; + private static final String TENANT_DOMAIN = "wso2.com"; + + @BeforeClass + public void setUp() { + + defaultRoleManagementListener = spy(new DefaultRoleManagementListener()); + } + + @DataProvider(name = "fragmentAppPropertyProvider") + public Object[][] fragmentAppPropertyProvider() { + + // Creating main application object. + ServiceProvider mainApplication = createServiceProvider(); + mainApplication.setSpProperties(null); + + // Creating shared application object. + ServiceProvider fragmentApplication = createServiceProvider(); + ServiceProviderProperty isFragmentAppSpProp = buildServiceProviderProperty(IS_FRAGMENT_APP, + Boolean.TRUE.toString()); + fragmentApplication.setSpProperties(new ServiceProviderProperty[]{isFragmentAppSpProp}); + + return new Object[][] { + {false, mainApplication}, + {true, fragmentApplication} + }; + } + + @Test(priority = 1, dataProvider = "fragmentAppPropertyProvider") + public void testPreAddRoleForFragmentApp(boolean isFragmentApp, ServiceProvider application) throws Exception { + + try (MockedStatic applicationManagementServiceMockedStatic = + mockStatic(ApplicationManagementService.class)) { + + ApplicationManagementService applicationManagementService = mock(ApplicationManagementService.class); + applicationManagementServiceMockedStatic.when(ApplicationManagementService::getInstance). + thenReturn(applicationManagementService); + when(applicationManagementService.getApplicationByResourceId(anyString(), anyString())). + thenReturn(application); + when(applicationManagementService.getAllowedAudienceForRoleAssociation(anyString(), anyString())). + thenReturn(APPLICATION_AUD); + + // Calling the preAddRole method. + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION_AUD, APPLICATION_RES_ID, TENANT_DOMAIN); + + Map threadLocalProps = IdentityUtil.threadLocalProperties.get(); + if (!isFragmentApp) { + assertFalse(threadLocalProps.containsKey(IS_FRAGMENT_APP)); + } else { + // If the application is a fragment app, then we add the IS_FRAGMENT_APP property to the thread local. + assertTrue(threadLocalProps.containsKey(IS_FRAGMENT_APP)); + } + // Clearing the thread local properties. + IdentityUtil.threadLocalProperties.set(new HashMap<>()); + } + } + + @Test(priority = 2, dataProvider = "fragmentAppPropertyProvider") + public void testPreAddRoleWhenPreviousFragmentPropertyNotCleared(boolean isFragmentApp, + ServiceProvider application) throws Exception { + + try (MockedStatic applicationManagementServiceMockedStatic = + mockStatic(ApplicationManagementService.class)) { + + ApplicationManagementService applicationManagementService = mock(ApplicationManagementService.class); + applicationManagementServiceMockedStatic.when(ApplicationManagementService::getInstance). + thenReturn(applicationManagementService); + when(applicationManagementService.getApplicationByResourceId(anyString(), anyString())). + thenReturn(application); + when(applicationManagementService.getAllowedAudienceForRoleAssociation(anyString(), anyString())). + thenReturn(APPLICATION_AUD); + + // Mimicking the scenario where the previous fragment property is not cleared in the thread local. + Map threadLocalProps = new HashMap<>(); + threadLocalProps.put(IS_FRAGMENT_APP, Boolean.TRUE); + IdentityUtil.threadLocalProperties.set(threadLocalProps); + + // Calling the preAddRole method. + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION_AUD, APPLICATION_RES_ID, TENANT_DOMAIN); + + if (!isFragmentApp) { + assertFalse(threadLocalProps.containsKey(IS_FRAGMENT_APP)); + } else { + // If the application is a fragment app, then we add the IS_FRAGMENT_APP property to the thread local. + assertTrue(threadLocalProps.containsKey(IS_FRAGMENT_APP)); + } + // Clearing the thread local properties. + IdentityUtil.threadLocalProperties.set(new HashMap<>()); + } + } + + @Test(priority = 3) + public void testPreAddRoleWithOtherSPProperties() throws Exception { + + try (MockedStatic applicationManagementServiceMockedStatic = + mockStatic(ApplicationManagementService.class)) { + + // Creating service provider object. + ServiceProvider serviceProvider = createServiceProvider(); + + // Creating service provider property object. + ServiceProviderProperty isFragmentAppSpProp = buildServiceProviderProperty("test-prop-name", + "test-prop-value"); + serviceProvider.setSpProperties(new ServiceProviderProperty[]{isFragmentAppSpProp}); + + ApplicationManagementService applicationManagementService = mock(ApplicationManagementService.class); + applicationManagementServiceMockedStatic.when(ApplicationManagementService::getInstance). + thenReturn(applicationManagementService); + when(applicationManagementService.getApplicationByResourceId(anyString(), anyString())). + thenReturn(serviceProvider); + when(applicationManagementService.getAllowedAudienceForRoleAssociation(anyString(), anyString())). + thenReturn(APPLICATION_AUD); + + // Calling the preAddRole method. + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION_AUD, APPLICATION_RES_ID, TENANT_DOMAIN); + + assertFalse(IdentityUtil.threadLocalProperties.get().containsKey(IS_FRAGMENT_APP)); + } + } + + @Test(priority = 4) + public void testPreAddRoleForOrgAudience() throws Exception { + + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), ORGANIZATION_AUD, "org-id", TENANT_DOMAIN); + // If the audience is not application, then in the preAddRole method, it will return without going to the + // other methods. So the thread local properties will not be set. + Map threadLocalProps = IdentityUtil.threadLocalProperties.get(); + assertFalse(threadLocalProps.containsKey(IS_FRAGMENT_APP)); + } + + @Test(priority = 5, expectedExceptions = {IdentityRoleManagementClientException.class}, + expectedExceptionsMessageRegExp = "Invalid audience. No application found with application id: " + + APPLICATION_RES_ID + " and tenant domain : " + TENANT_DOMAIN) + public void testPreAddRoleWithNullApplication() throws Exception { + + try (MockedStatic applicationManagementServiceMockedStatic = + mockStatic(ApplicationManagementService.class)) { + + ApplicationManagementService applicationManagementService = mock(ApplicationManagementService.class); + applicationManagementServiceMockedStatic.when(ApplicationManagementService::getInstance). + thenReturn(applicationManagementService); + when(applicationManagementService.getApplicationByResourceId(anyString(), anyString())). + thenReturn(null); + // Calling the preAddRole method. + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION_AUD, APPLICATION_RES_ID, TENANT_DOMAIN); + } + } + + @Test(priority = 6, expectedExceptions = {IdentityRoleManagementClientException.class}, + expectedExceptionsMessageRegExp = "Application: " + APPLICATION_RES_ID + " does not have Application " + + "role audience type") + public void testPreAddRoleWithWrongAudience() throws Exception { + + try (MockedStatic applicationManagementServiceMockedStatic = + mockStatic(ApplicationManagementService.class)) { + + // Creating service provider object. + ServiceProvider serviceProvider = createServiceProvider(); + + ApplicationManagementService applicationManagementService = mock(ApplicationManagementService.class); + applicationManagementServiceMockedStatic.when(ApplicationManagementService::getInstance). + thenReturn(applicationManagementService); + when(applicationManagementService.getApplicationByResourceId(anyString(), anyString())). + thenReturn(serviceProvider); + when(applicationManagementService.getAllowedAudienceForRoleAssociation(anyString(), anyString())). + thenReturn(ORGANIZATION_AUD); + // Calling the preAddRole method. + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION_AUD, APPLICATION_RES_ID, TENANT_DOMAIN); + } + } + + @Test(priority = 7, expectedExceptions = {IdentityRoleManagementServerException.class}, + expectedExceptionsMessageRegExp = "Error while retrieving the application for the given id: " + + APPLICATION_RES_ID) + public void testPreAddRoleWithApplicationRetrievingException() throws Exception { + + try (MockedStatic applicationManagementServiceMockedStatic = + mockStatic(ApplicationManagementService.class)) { + + ApplicationManagementService applicationManagementService = mock(ApplicationManagementService.class); + applicationManagementServiceMockedStatic.when(ApplicationManagementService::getInstance). + thenReturn(applicationManagementService); + when(applicationManagementService.getApplicationByResourceId(anyString(), anyString())). + thenThrow(IdentityApplicationManagementException.class); + + // Calling the preAddRole method. + defaultRoleManagementListener.preAddRole(ROLE_NAME, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION_AUD, APPLICATION_RES_ID, TENANT_DOMAIN); + } + } + + private static ServiceProviderProperty buildServiceProviderProperty(String name, String value) { + + ServiceProviderProperty isFragmentAppSpProp = new ServiceProviderProperty(); + isFragmentAppSpProp.setName(name); + isFragmentAppSpProp.setValue(value); + return isFragmentAppSpProp; + } + + private static ServiceProvider createServiceProvider() { + + ServiceProvider serviceProvider = new ServiceProvider(); + serviceProvider.setApplicationName(APPLICATION_NAME); + serviceProvider.setApplicationResourceId(APPLICATION_RES_ID); + return serviceProvider; + } +} diff --git a/components/application-mgt/pom.xml b/components/application-mgt/pom.xml index 994c49e0d573..6b6dee1cf910 100644 --- a/components/application-mgt/pom.xml +++ b/components/application-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml index d378332e9d74..6cdabcdef25b 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.endpoint.util/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework authentication-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/pom.xml b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/pom.xml index 9bb4b789b1c6..7bc82b5c10a9 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/pom.xml +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework authentication-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultAuthenticationRequestHandler.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultAuthenticationRequestHandler.java index 23fbab72abc3..53a0ee078cbd 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultAuthenticationRequestHandler.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/handler/request/impl/DefaultAuthenticationRequestHandler.java @@ -66,6 +66,7 @@ import org.wso2.carbon.idp.mgt.IdentityProviderManagementException; import org.wso2.carbon.idp.mgt.IdentityProviderManager; import org.wso2.carbon.idp.mgt.util.IdPManagementUtil; +import org.wso2.carbon.user.core.UserCoreConstants; import org.wso2.carbon.user.core.config.UserStorePreferenceOrderSupplier; import org.wso2.carbon.user.core.model.UserMgtContext; import org.wso2.carbon.user.core.util.UserCoreUtil; @@ -576,7 +577,9 @@ protected void concludeFlow(HttpServletRequest request, HttpServletResponse resp context.getLoginTenantDomain()); // Since the session context is already available, audit log will be added with updated details. addAuditLogs(SessionMgtConstants.UPDATE_SESSION_ACTION, - authenticationResult.getSubject().getUserName(), sessionContextKey, + authenticationResult.getSubject().getUserStoreDomain() + + UserCoreConstants.DOMAIN_SEPARATOR + + authenticationResult.getSubject().getUserName(), sessionContextKey, authenticationResult.getSubject().getTenantDomain(), FrameworkUtils.getCorrelation(), updatedSessionTime, sessionContext.isRememberMe()); } else { @@ -624,7 +627,9 @@ protected void concludeFlow(HttpServletRequest request, HttpServletResponse resp // The session context will be stored from here. Since the audit log will be logged as a storing // operation. addAuditLogs(SessionMgtConstants.STORE_SESSION_ACTION, - authenticationResult.getSubject().getUserName(), sessionContextKey, + authenticationResult.getSubject().getUserStoreDomain() + + UserCoreConstants.DOMAIN_SEPARATOR + + authenticationResult.getSubject().getUserName(), sessionContextKey, authenticationResult.getSubject().getTenantDomain(), FrameworkUtils.getCorrelation(), createdTimeMillis, sessionContext.isRememberMe()); if (request.getAttribute(ALLOW_SESSION_CREATION) == null @@ -703,6 +708,13 @@ protected void concludeFlow(HttpServletRequest request, HttpServletResponse resp } } + // Adding locally mapped remote claims to authentication results. + if (context.getProperty(FrameworkConstants.UNFILTERED_LOCAL_CLAIM_VALUES) instanceof Map) { + Map mappedRemoteClaims = + (Map) context.getProperty(FrameworkConstants.UNFILTERED_LOCAL_CLAIM_VALUES); + authenticationResult.setMappedRemoteClaims(mappedRemoteClaims); + } + // Checking weather inbound protocol is an already cache removed one, request come from federated or other // authenticator in multi steps scenario. Ex. Fido if (FrameworkUtils.getCacheDisabledAuthenticators().contains(context.getRequestType()) diff --git a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/model/AuthenticationResult.java b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/model/AuthenticationResult.java index e913770be427..808bf82470c4 100644 --- a/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/model/AuthenticationResult.java +++ b/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/model/AuthenticationResult.java @@ -21,6 +21,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import java.util.Optional; /** * Authentication result. @@ -36,6 +37,10 @@ public class AuthenticationResult implements Serializable { private boolean isSaaSApp; private boolean loggedOut; private Map claimMapping; + /** + * Unfiltered remote claims that mapped to local claims. + */ + private Map mappedRemoteClaims; private Map properties = new HashMap<>(); public AuthenticationResult() { @@ -111,4 +116,14 @@ public void addProperty(String key, Object value) { public Object getProperty(String key) { return properties.get(key); } + + public Optional> getMappedRemoteClaims() { + + return Optional.ofNullable(mappedRemoteClaims); + } + + public void setMappedRemoteClaims(Map mappedRemoteClaims) { + + this.mappedRemoteClaims = mappedRemoteClaims; + } } diff --git a/components/authentication-framework/pom.xml b/components/authentication-framework/pom.xml index 1d7e38c85a63..3c70cb28314a 100644 --- a/components/authentication-framework/pom.xml +++ b/components/authentication-framework/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/captcha-mgt/org.wso2.carbon.captcha.mgt/pom.xml b/components/captcha-mgt/org.wso2.carbon.captcha.mgt/pom.xml index a40d1885f12b..093089265918 100644 --- a/components/captcha-mgt/org.wso2.carbon.captcha.mgt/pom.xml +++ b/components/captcha-mgt/org.wso2.carbon.captcha.mgt/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework captcha-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/captcha-mgt/pom.xml b/components/captcha-mgt/pom.xml index b2944c4e8e61..f3af2af34115 100644 --- a/components/captcha-mgt/pom.xml +++ b/components/captcha-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/carbon-authenticators/pom.xml b/components/carbon-authenticators/pom.xml index 141fe31e9d8b..a8c8f0fda24b 100644 --- a/components/carbon-authenticators/pom.xml +++ b/components/carbon-authenticators/pom.xml @@ -17,7 +17,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.authenticator.thrift/pom.xml b/components/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.authenticator.thrift/pom.xml index 420f9182a30a..a3b5cd8c0a4f 100644 --- a/components/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.authenticator.thrift/pom.xml +++ b/components/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.authenticator.thrift/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework thrift-authenticator - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/carbon-authenticators/thrift-authenticator/pom.xml b/components/carbon-authenticators/thrift-authenticator/pom.xml index 134c38135a77..269b058a9e43 100644 --- a/components/carbon-authenticators/thrift-authenticator/pom.xml +++ b/components/carbon-authenticators/thrift-authenticator/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework carbon-authenticators - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/central-logger/org.wso2.carbon.identity.central.log.mgt/pom.xml b/components/central-logger/org.wso2.carbon.identity.central.log.mgt/pom.xml index 30aca688b16a..9964f064f351 100644 --- a/components/central-logger/org.wso2.carbon.identity.central.log.mgt/pom.xml +++ b/components/central-logger/org.wso2.carbon.identity.central.log.mgt/pom.xml @@ -21,7 +21,7 @@ central-logger org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/central-logger/pom.xml b/components/central-logger/pom.xml index 52daf8b6277e..5afec82235bf 100644 --- a/components/central-logger/pom.xml +++ b/components/central-logger/pom.xml @@ -21,7 +21,7 @@ identity-framework org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/pom.xml b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/pom.xml index 19d0c2f0a797..eaed4d7f1d6a 100644 --- a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework certificate-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT 4.0.0 @@ -75,7 +75,6 @@ ${project.artifactId} - org.wso2.carbon.identity.certificate.management.cache, org.wso2.carbon.identity.certificate.management.constant, org.wso2.carbon.identity.certificate.management.dao.*, org.wso2.carbon.identity.certificate.management.internal, @@ -83,6 +82,7 @@ org.wso2.carbon.identity.certificate.management.util; + org.wso2.carbon.identity.certificate.management.cache, org.wso2.carbon.identity.certificate.management.exception, org.wso2.carbon.identity.certificate.management.model, org.wso2.carbon.identity.certificate.management.service; diff --git a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/cache/CertificateIdCacheKey.java b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/cache/CertificateIdCacheKey.java index 635f4aac07b6..fa555ed729cb 100644 --- a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/cache/CertificateIdCacheKey.java +++ b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/cache/CertificateIdCacheKey.java @@ -25,6 +25,7 @@ */ public class CertificateIdCacheKey extends CacheKey { + private static final long serialVersionUID = 5691238745928475691L; private final String certificateId; public CertificateIdCacheKey(String certificateId) { diff --git a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/ApplicationCertificateManagementDAOImpl.java b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/ApplicationCertificateManagementDAOImpl.java index 0c50f0642b6d..aab63ba3acdf 100644 --- a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/ApplicationCertificateManagementDAOImpl.java +++ b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/ApplicationCertificateManagementDAOImpl.java @@ -62,7 +62,7 @@ public int addCertificate(String certificateId, Certificate certificate, int ten int index = 1; preparedStatement.setString(index++, certificateId); preparedStatement.setString(index++, certificate.getName()); - preparedStatement.setBlob(index++, certByteStream, certificateLength); + preparedStatement.setBinaryStream(index++, certByteStream, certificateLength); preparedStatement.setInt(index, tenantId); }, certificate, true)); } catch (TransactionException | IOException e) { @@ -145,7 +145,7 @@ public void updateCertificateContent(int certificateId, String certificateConten template.executeUpdate(ApplicationCertificateMgtSQLQueries.UPDATE_CERTIFICATE_CONTENT, preparedStatement -> { int index = 1; - preparedStatement.setBlob(index++, certByteStream, certificateLength); + preparedStatement.setBinaryStream(index++, certByteStream, certificateLength); preparedStatement.setInt(index++, certificateId); preparedStatement.setInt(index, tenantId); }); diff --git a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/CertificateManagementDAOImpl.java b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/CertificateManagementDAOImpl.java index 856f4eae1f1b..fb7c6c541026 100644 --- a/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/CertificateManagementDAOImpl.java +++ b/components/certificate-mgt/org.wso2.carbon.identity.certificate.management/src/main/java/org/wso2/carbon/identity/certificate/management/dao/impl/CertificateManagementDAOImpl.java @@ -57,7 +57,7 @@ public void addCertificate(String certificateId, Certificate certificate, int te int index = 1; preparedStatement.setString(index++, certificateId); preparedStatement.setString(index++, certificate.getName()); - preparedStatement.setBlob(index++, certByteStream, certificateLength); + preparedStatement.setBinaryStream(index++, certByteStream, certificateLength); preparedStatement.setInt(index, tenantId); }, certificate, false); return null; @@ -109,7 +109,7 @@ public void updateCertificateContent(String certificateId, String certificateCon template.executeUpdate(CertificateMgtSQLConstants.Query.UPDATE_CERTIFICATE_CONTENT, preparedStatement -> { int index = 1; - preparedStatement.setBlob(index++, certByteStream, certificateLength); + preparedStatement.setBinaryStream(index++, certByteStream, certificateLength); preparedStatement.setString(index++, certificateId); preparedStatement.setInt(index, tenantId); }); diff --git a/components/certificate-mgt/pom.xml b/components/certificate-mgt/pom.xml index 7ad187a12bef..0e711c98069a 100644 --- a/components/certificate-mgt/pom.xml +++ b/components/certificate-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/claim-mgt/org.wso2.carbon.claim.mgt.ui/pom.xml b/components/claim-mgt/org.wso2.carbon.claim.mgt.ui/pom.xml index e1e2b716a04a..deb188477fe6 100644 --- a/components/claim-mgt/org.wso2.carbon.claim.mgt.ui/pom.xml +++ b/components/claim-mgt/org.wso2.carbon.claim.mgt.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework claim-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/claim-mgt/org.wso2.carbon.claim.mgt/pom.xml b/components/claim-mgt/org.wso2.carbon.claim.mgt/pom.xml index e004fbb455a7..f1b7826787d3 100644 --- a/components/claim-mgt/org.wso2.carbon.claim.mgt/pom.xml +++ b/components/claim-mgt/org.wso2.carbon.claim.mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework claim-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt.ui/pom.xml b/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt.ui/pom.xml index 57eacc7a5a8f..66fa85612551 100644 --- a/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt.ui/pom.xml +++ b/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt.ui/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework claim-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt/pom.xml b/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt/pom.xml index 28d4527300e5..b788807e7e95 100644 --- a/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt/pom.xml +++ b/components/claim-mgt/org.wso2.carbon.identity.claim.metadata.mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework claim-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/claim-mgt/pom.xml b/components/claim-mgt/pom.xml index ae1d1e941b9b..e5ffa569c0e2 100644 --- a/components/claim-mgt/pom.xml +++ b/components/claim-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt/pom.xml b/components/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt/pom.xml index 8e86ded6cc90..abb0f79d8ce8 100644 --- a/components/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt/pom.xml +++ b/components/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework client-attestation-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/client-attestation-mgt/pom.xml b/components/client-attestation-mgt/pom.xml index 0560f9d19470..26de12cfc41b 100644 --- a/components/client-attestation-mgt/pom.xml +++ b/components/client-attestation-mgt/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/configuration-mgt/org.wso2.carbon.identity.api.server.configuration.mgt/pom.xml b/components/configuration-mgt/org.wso2.carbon.identity.api.server.configuration.mgt/pom.xml index 6a99bb45e91c..d2bad4836307 100644 --- a/components/configuration-mgt/org.wso2.carbon.identity.api.server.configuration.mgt/pom.xml +++ b/components/configuration-mgt/org.wso2.carbon.identity.api.server.configuration.mgt/pom.xml @@ -23,11 +23,11 @@ org.wso2.carbon.identity.framework configuration-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT org.wso2.carbon.identity.api.server.configuration.mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT jar WSO2 Carbon - Configuration Management API Identity Configuration Management API diff --git a/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.core/pom.xml b/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.core/pom.xml index aa9e399fe394..161385ed7cbc 100644 --- a/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.core/pom.xml +++ b/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.core/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework configuration-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.endpoint/pom.xml b/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.endpoint/pom.xml index e2830621b231..97bb5c71b122 100644 --- a/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.endpoint/pom.xml +++ b/components/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.endpoint/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework configuration-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/configuration-mgt/pom.xml b/components/configuration-mgt/pom.xml index cf2427c42fe7..c0d89e2625b2 100644 --- a/components/configuration-mgt/pom.xml +++ b/components/configuration-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/consent-mgt/org.wso2.carbon.identity.consent.mgt/pom.xml b/components/consent-mgt/org.wso2.carbon.identity.consent.mgt/pom.xml index 375b7a1b5313..937d543b96ee 100644 --- a/components/consent-mgt/org.wso2.carbon.identity.consent.mgt/pom.xml +++ b/components/consent-mgt/org.wso2.carbon.identity.consent.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework consent-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/consent-mgt/pom.xml b/components/consent-mgt/pom.xml index 742caeee3d1b..3c2fb1619a96 100644 --- a/components/consent-mgt/pom.xml +++ b/components/consent-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt/pom.xml b/components/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt/pom.xml index bf0a11e5ad4a..857cce3c0f15 100644 --- a/components/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt/pom.xml +++ b/components/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework consent-server-configs-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/consent-server-configs-mgt/pom.xml b/components/consent-server-configs-mgt/pom.xml index 19cd85fbdcb5..ccdc9e7d8e97 100644 --- a/components/consent-server-configs-mgt/pom.xml +++ b/components/consent-server-configs-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/cors-mgt/org.wso2.carbon.identity.cors.mgt.core/pom.xml b/components/cors-mgt/org.wso2.carbon.identity.cors.mgt.core/pom.xml index 66e95a8d0e32..376030a3ea5c 100644 --- a/components/cors-mgt/org.wso2.carbon.identity.cors.mgt.core/pom.xml +++ b/components/cors-mgt/org.wso2.carbon.identity.cors.mgt.core/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework cors-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/cors-mgt/pom.xml b/components/cors-mgt/pom.xml index 6c7a71901805..0286c021587c 100644 --- a/components/cors-mgt/pom.xml +++ b/components/cors-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/directory-server-manager/org.wso2.carbon.directory.server.manager.common/pom.xml b/components/directory-server-manager/org.wso2.carbon.directory.server.manager.common/pom.xml index 434244890d55..89ef0f9cb40b 100644 --- a/components/directory-server-manager/org.wso2.carbon.directory.server.manager.common/pom.xml +++ b/components/directory-server-manager/org.wso2.carbon.directory.server.manager.common/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework directory-server-manager - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/directory-server-manager/org.wso2.carbon.directory.server.manager.ui/pom.xml b/components/directory-server-manager/org.wso2.carbon.directory.server.manager.ui/pom.xml index ff25a6cd772c..4d0b1a8a03ca 100644 --- a/components/directory-server-manager/org.wso2.carbon.directory.server.manager.ui/pom.xml +++ b/components/directory-server-manager/org.wso2.carbon.directory.server.manager.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework directory-server-manager - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/directory-server-manager/org.wso2.carbon.directory.server.manager/pom.xml b/components/directory-server-manager/org.wso2.carbon.directory.server.manager/pom.xml index 5a9353dffeed..d9a16dcd6821 100644 --- a/components/directory-server-manager/org.wso2.carbon.directory.server.manager/pom.xml +++ b/components/directory-server-manager/org.wso2.carbon.directory.server.manager/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework directory-server-manager - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/directory-server-manager/pom.xml b/components/directory-server-manager/pom.xml index 9f295a2dfe4b..78307d7996f3 100644 --- a/components/directory-server-manager/pom.xml +++ b/components/directory-server-manager/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/extension-mgt/org.wso2.carbon.identity.extension.mgt/pom.xml b/components/extension-mgt/org.wso2.carbon.identity.extension.mgt/pom.xml index d631930839fa..4b6df2cfcd35 100644 --- a/components/extension-mgt/org.wso2.carbon.identity.extension.mgt/pom.xml +++ b/components/extension-mgt/org.wso2.carbon.identity.extension.mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework extension-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/extension-mgt/pom.xml b/components/extension-mgt/pom.xml index 7f6371ba2f3b..e64965a68030 100644 --- a/components/extension-mgt/pom.xml +++ b/components/extension-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui/pom.xml b/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui/pom.xml index 39d5330a4e3d..55bbf01347aa 100644 --- a/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui/pom.xml +++ b/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui/pom.xml @@ -21,7 +21,7 @@ functions-library-mgt org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt/pom.xml b/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt/pom.xml index baac745154da..30773f18e57a 100644 --- a/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt/pom.xml +++ b/components/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt/pom.xml @@ -21,7 +21,7 @@ functions-library-mgt org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/functions-library-mgt/pom.xml b/components/functions-library-mgt/pom.xml index 1c37402e0aa8..dad90fd9fa65 100644 --- a/components/functions-library-mgt/pom.xml +++ b/components/functions-library-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/identity-core/org.wso2.carbon.identity.base/pom.xml b/components/identity-core/org.wso2.carbon.identity.base/pom.xml index 386540160899..1c6a54ae9bfc 100644 --- a/components/identity-core/org.wso2.carbon.identity.base/pom.xml +++ b/components/identity-core/org.wso2.carbon.identity.base/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-core - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/identity-core/org.wso2.carbon.identity.base/src/main/java/org/wso2/carbon/identity/base/AuthenticatorPropertyConstants.java b/components/identity-core/org.wso2.carbon.identity.base/src/main/java/org/wso2/carbon/identity/base/AuthenticatorPropertyConstants.java index a887fd052c80..4b796e87bd0a 100644 --- a/components/identity-core/org.wso2.carbon.identity.base/src/main/java/org/wso2/carbon/identity/base/AuthenticatorPropertyConstants.java +++ b/components/identity-core/org.wso2.carbon.identity.base/src/main/java/org/wso2/carbon/identity/base/AuthenticatorPropertyConstants.java @@ -20,6 +20,9 @@ public class AuthenticatorPropertyConstants { + public static final String TAG_2FA = "2FA"; + public static final String TAG_CUSTOM = "Custom"; + /** * The Defined by Types - SYSTEM: system define authenticator, USER: user defined authentication extension. */ diff --git a/components/identity-core/org.wso2.carbon.identity.core.ui/pom.xml b/components/identity-core/org.wso2.carbon.identity.core.ui/pom.xml index 27441f20d236..c9e9dad80c39 100644 --- a/components/identity-core/org.wso2.carbon.identity.core.ui/pom.xml +++ b/components/identity-core/org.wso2.carbon.identity.core.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-core - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/identity-core/org.wso2.carbon.identity.core/pom.xml b/components/identity-core/org.wso2.carbon.identity.core/pom.xml index 96f28e069783..9d0e030a0416 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/pom.xml +++ b/components/identity-core/org.wso2.carbon.identity.core/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-core - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml @@ -213,6 +213,7 @@ org.apache.commons.collections; version="${commons-collections.wso2.osgi.version.range}", org.apache.commons.collections4; version = "${commons-collections4.wso2.osgi.version.range}", ua_parser; version="${ua_parser.version.range}", + org.wso2.carbon.utils.security;version="${carbon.kernel.package.import.version.range}", !org.wso2.carbon.identity.core.internal, diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolver.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolver.java index 1c05a79b5182..480750f6d206 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolver.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolver.java @@ -246,6 +246,78 @@ public Key getPrivateKey(String tenantDomain, InboundProtocol inboundProtocol) return getPrivateKey(tenantDomain); } + /** + * Retrieves the public certificate for a given tenant domain and context. + *

+ * This method fetches the public certificate associated with a specific tenant domain and context. + * If the context is blank, it delegates the call to the overloaded + * {@code getCertificate(String tenantDomain)} method. + * The method first checks if the certificate is cached; if not, it retrieves the certificate from + * the KeyStoreManager, caches it, and then returns it. + *

+ * + * @param tenantDomain the tenant domain for which the certificate is requested. + * @param context the specific context for the tenant's certificate. If blank, the default certificate for the tenant is fetched. + * @return the public certificate for the specified tenant domain and context. + * @throws IdentityKeyStoreResolverException if there is an error while retrieving the certificate. + */ + + private Certificate getCertificate(String tenantDomain, String context) throws IdentityKeyStoreResolverException { + + if (StringUtils.isBlank(context)) { + getCertificate(tenantDomain); + } + int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); + + if (publicCerts.containsKey(buildTenantIdWithContext(tenantId, context))) { + return publicCerts.get(buildTenantIdWithContext(tenantId, context)); + } + + KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); + Certificate publicCert; + String tenantKeyStoreName = IdentityKeyStoreResolverUtil.buildTenantKeyStoreName(tenantDomain, context); + try { + publicCert = keyStoreManager.getCertificate(tenantKeyStoreName, tenantDomain + + IdentityKeyStoreResolverConstants.KEY_STORE_CONTEXT_SEPARATOR + context); + + } catch (SecurityException e) { + if (e.getMessage() != null && e.getMessage().contains("Key Store with a name: " + tenantKeyStoreName + + " does not exist.")) { + + throw new IdentityKeyStoreResolverException( + ErrorMessages.ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST.getCode(), + String.format( + ErrorMessages.ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST + .getDescription(), tenantDomain), e); + } else { + throw new IdentityKeyStoreResolverException( + ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE.getCode(), + String.format(ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE.getDescription(), + tenantDomain), e); + } + } catch (Exception e) { + throw new IdentityKeyStoreResolverException( + ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE.getCode(), + String.format(ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE.getDescription(), + tenantDomain), e); + } + + publicCerts.put(buildTenantIdWithContext(tenantId, context), publicCert); + return publicCert; + } + + /** + * Concatenates tenantId and context with the separator. + * + * @param tenantId the key store name + * @param context the context + * @return a concatenated string in the format tenantDomain:context + */ + private String buildTenantIdWithContext(int tenantId, String context) { + + return tenantId + IdentityKeyStoreResolverConstants.KEY_STORE_CONTEXT_SEPARATOR + context; + } + /** * Return Public Certificate of the Primary or tenant keystore according to given tenant domain. * @@ -285,17 +357,22 @@ private Certificate getCertificate(String tenantDomain) throws IdentityKeyStoreR * * @param tenantDomain Tenant domain. * @param inboundProtocol Inbound authentication protocol of the application. + * @param context Context of the keystore. * @return Public Certificate of the Primary, tenant or custom keystore. * @throws IdentityKeyStoreResolverException the exception in the IdentityKeyStoreResolver class. */ - public Certificate getCertificate(String tenantDomain, InboundProtocol inboundProtocol) + public Certificate getCertificate(String tenantDomain, InboundProtocol inboundProtocol, String context) throws IdentityKeyStoreResolverException { + if (StringUtils.isEmpty(tenantDomain)) { throw new IdentityKeyStoreResolverException( ErrorMessages.ERROR_CODE_INVALID_ARGUMENT.getCode(), String.format(ErrorMessages.ERROR_CODE_INVALID_ARGUMENT.getDescription(), "Tenant domain")); } + if (context != null) { + return getCertificate(tenantDomain, context); + } if (inboundProtocol == null) { return getCertificate(tenantDomain); } @@ -326,13 +403,27 @@ public Certificate getCertificate(String tenantDomain, InboundProtocol inboundPr throw new IdentityKeyStoreResolverException( ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_CUSTOM_PUBLIC_CERTIFICATE.getCode(), String.format(ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_CUSTOM_PUBLIC_CERTIFICATE - .getDescription(), keyStoreName), e); + .getDescription(), keyStoreName), e); } } } return getCertificate(tenantDomain); } + /** + * Return Public Certificate of the Primary, tenant or custom keystore. + * + * @param tenantDomain Tenant domain. + * @param inboundProtocol Inbound authentication protocol of the application. + * @return Public Certificate of the Primary, tenant or custom keystore. + * @throws IdentityKeyStoreResolverException the exception in the IdentityKeyStoreResolver class. + */ + public Certificate getCertificate(String tenantDomain, InboundProtocol inboundProtocol) + throws IdentityKeyStoreResolverException { + + return getCertificate(tenantDomain, inboundProtocol, null); + } + /** * Return Public Key of the Primary or tenant keystore according to given tenant domain. * diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverConstants.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverConstants.java index def4bdd725d6..795ed078dd6a 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverConstants.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverConstants.java @@ -41,6 +41,7 @@ public class IdentityKeyStoreResolverConstants { // KeyStore Constants. public static final String KEY_STORE_EXTENSION = ".jks"; + public static final String KEY_STORE_CONTEXT_SEPARATOR = "--"; // Inbound Protocols. public static final String INBOUND_PROTOCOL_OAUTH = "oauth"; @@ -119,6 +120,10 @@ public enum ErrorMessages { ERROR_CODE_ERROR_RETRIEVING_CUSTOM_KEYSTORE_CONFIGURATION( "IKSR-10009", "Error retrieving custom keystore configuration.", "Error occurred when retrieving custom keystore configuration for: %s."), + ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST( + "IKSR-10010", "Error retrieving context public certificate. Keystore doesn't exist.", + "Error occurred when retrieving context certificate for tenant: %s. " + + "Context Keystore doesn't exist."), // Errors occurred within the IdentityKeyStoreResolver ERROR_CODE_INVALID_ARGUMENT( diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtil.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtil.java index 98295af64c9b..da0b99e69bfd 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtil.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtil.java @@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils; import org.wso2.carbon.core.RegistryResources; import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants.ErrorMessages; +import org.wso2.carbon.utils.security.KeystoreUtils; import javax.xml.namespace.QName; @@ -38,13 +39,41 @@ public class IdentityKeyStoreResolverUtil { */ public static String buildTenantKeyStoreName(String tenantDomain) throws IdentityKeyStoreResolverException { + return buildTenantKeyStoreName(tenantDomain, null); + } + + /** + * Builds the keystore name for a given tenant domain and context. + * The tenant domain is sanitized by replacing dots (.) with hyphens (-) to ensure compatibility + * with keystore naming conventions. If a context is provided, it is appended to the sanitized + * tenant domain with an underscore (_). The method also appends the standard keystore file + * extension as defined in {@link IdentityKeyStoreResolverConstants}. + * + * @param tenantDomain The domain name of the tenant (e.g., "example.com"). + * @param context The optional context to append to the tenant keystore name. + * @return A sanitized and formatted keystore name for the tenant. + * @throws IdentityKeyStoreResolverException If the tenant domain is null, empty, or invalid. + */ + public static String buildTenantKeyStoreName(String tenantDomain, String context) + throws IdentityKeyStoreResolverException { + + // Validate tenantDomain argument if (StringUtils.isEmpty(tenantDomain)) { throw new IdentityKeyStoreResolverException( ErrorMessages.ERROR_CODE_INVALID_ARGUMENT.getCode(), String.format(ErrorMessages.ERROR_CODE_INVALID_ARGUMENT.getDescription(), "Tenant domain")); } + + // Sanitize tenant domain: replace '.' with '-' String ksName = tenantDomain.trim().replace(".", "-"); - return ksName + IdentityKeyStoreResolverConstants.KEY_STORE_EXTENSION; + + // Append context if provided + if (StringUtils.isNotBlank(context)) { + ksName = buildDomainWithContext(ksName, context); + } + + // Add the keystore extension + return ksName + KeystoreUtils.getKeyStoreFileExtension(tenantDomain); } /** @@ -74,4 +103,16 @@ public static QName getQNameWithIdentityNameSpace(String localPart) { return new QName(IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, localPart); } + + /** + * Concatenates tenantDomain and context with the separator. + * + * @param tenantDomain the key store name + * @param context the context + * @return a concatenated string in the format tenantDomain:context + */ + public static String buildDomainWithContext(String tenantDomain, String context) { + + return tenantDomain + IdentityKeyStoreResolverConstants.KEY_STORE_CONTEXT_SEPARATOR + context; + } } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityUtil.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityUtil.java index 7d9a51f7e6cd..bf9203020df3 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityUtil.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/util/IdentityUtil.java @@ -114,6 +114,7 @@ import static org.wso2.carbon.identity.core.util.IdentityCoreConstants.ENCODED_ZERO; import static org.wso2.carbon.identity.core.util.IdentityCoreConstants.INDEXES; import static org.wso2.carbon.identity.core.util.IdentityCoreConstants.USERS_LIST_PER_ROLE_LOWER_BOUND; +import static org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants.ErrorMessages.ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST; public class IdentityUtil { @@ -1969,6 +1970,61 @@ public static boolean isSCIM2UserMaxItemsPerPageEnabled() { return Boolean.parseBoolean(scim2UserMaxItemsPerPageEnabledProperty); } + /** + * Validates the provided signature for the given data using the public key of a specified tenant. + * + * The method retrieves the public key for the tenant from the certificate stored in the tenant's keystore. + * If a context is provided, the method attempts to retrieve the certificate within that context. + * + * @param data The data to validate the signature against. + * @param signature The signature to be validated. + * @param tenantDomain The domain name of the tenant whose public key should be used for validation. + * @param context The optional context for retrieving the tenant's certificate (can be null or blank). + * @return True if the signature is valid; false otherwise. + * @throws SignatureException If an error occurs while validating the signature or accessing tenant data. + */ + public static boolean validateSignatureFromTenant(String data, byte[] signature, String tenantDomain, + String context) throws SignatureException { + + // Retrieve tenant ID based on the tenant domain + int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); + try { + // Initialize the tenant's registry + IdentityTenantUtil.initializeRegistry(tenantId); + + // Retrieve the tenant's public key + PublicKey publicKey; + if (StringUtils.isBlank(context)) { + // Fetch certificate without context if context is null or blank + publicKey = IdentityKeyStoreResolver.getInstance() + .getCertificate(tenantDomain, null) + .getPublicKey(); + } else { + try { + // Fetch certificate within the provided context + Certificate certificate = IdentityKeyStoreResolver.getInstance() + .getCertificate(tenantDomain, null, context); + publicKey = certificate.getPublicKey(); + } catch (IdentityKeyStoreResolverException e) { + if (ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST.getCode() + .equals(e.getErrorCode())) { + // Context keystore not exits, hence return validation as false. + return false; + } else { + throw new SignatureException("Error while validating the signature for tenant: " + + tenantDomain, e); + } + } + } + + // Validate the signature using the retrieved public key + return SignatureUtil.validateSignature(data, signature, publicKey); + } catch (IdentityException e) { + // Log and throw an exception if an error occurs + throw new SignatureException("Error while validating the signature for tenant: " + tenantDomain, e); + } + } + /** * Validates the signature of the given data for the specified tenant domain. * @@ -1981,48 +2037,83 @@ public static boolean isSCIM2UserMaxItemsPerPageEnabled() { public static boolean validateSignatureFromTenant(String data, byte[] signature, String tenantDomain) throws SignatureException { - int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); - try { - IdentityTenantUtil.initializeRegistry(tenantId); - PublicKey publicKey = IdentityKeyStoreResolver.getInstance().getCertificate(tenantDomain, null) - .getPublicKey(); - return SignatureUtil.validateSignature(data, signature, publicKey); - } catch (IdentityException e) { - throw new SignatureException("Error while validating the signature from tenant: " + tenantDomain, e); - } + return validateSignatureFromTenant(data, signature, tenantDomain, null); } /** - * Sign the given data for the specified tenant domain. + * Signs the given data using the private key of the specified tenant. + * + * For super tenant domains, the default private key is used. For other tenants, the method retrieves the private + * key from the tenant's keystore. If a context is provided, it will attempt to retrieve the private key associated + * with that context. * * @param data The data to be signed. - * @param tenantDomain The tenant domain to which the data belongs. - * @return The signature of the data. - * @throws SignatureException If an error occurs during the signature generation process. + * @param tenantDomain The domain name of the tenant whose private key will be used for signing. + * @param context The optional context for retrieving the tenant's private key (can be null or blank). + * @return A byte array containing the signature for the provided data. + * @throws SignatureException If an error occurs while retrieving the private key or signing the data. */ - public static byte[] signWithTenantKey(String data, String tenantDomain) throws SignatureException { + public static byte[] signWithTenantKey(String data, String tenantDomain, String context) throws SignatureException { + // Get tenant ID from tenant domain int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); PrivateKey privateKey; if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { try { - privateKey = keyStoreManager.getDefaultPrivateKey(); + String tenantKeyStoreName = IdentityKeyStoreResolverUtil.buildTenantKeyStoreName(tenantDomain, context); + // Retrieve private key from the tenant's keystore + if (StringUtils.isBlank(context)) { + // Retrieve default private key for the super tenant + privateKey = keyStoreManager.getDefaultPrivateKey(); + } else { + privateKey = (PrivateKey) keyStoreManager.getPrivateKey(tenantKeyStoreName, + tenantDomain + + IdentityKeyStoreResolverConstants.KEY_STORE_CONTEXT_SEPARATOR + context); + } + } catch (Exception e) { - throw new SignatureException(String.format(IdentityKeyStoreResolverConstants.ErrorMessages - .ERROR_CODE_ERROR_RETRIEVING_TENANT_PRIVATE_KEY.getDescription(), tenantDomain), - e); + throw new SignatureException(String.format( + IdentityKeyStoreResolverConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_TENANT_PRIVATE_KEY + .getDescription(), + tenantDomain), e); } } else { try { - String tenantKeyStoreName = IdentityKeyStoreResolverUtil.buildTenantKeyStoreName(tenantDomain); + // Build tenant keystore name + String tenantKeyStoreName = IdentityKeyStoreResolverUtil.buildTenantKeyStoreName(tenantDomain, context); + + // Initialize the tenant's registry IdentityTenantUtil.initializeRegistry(tenantId); - privateKey = (PrivateKey) keyStoreManager.getPrivateKey(tenantKeyStoreName, tenantDomain); + + // Retrieve private key from the tenant's keystore + if (StringUtils.isBlank(context)) { + privateKey = (PrivateKey) keyStoreManager.getPrivateKey(tenantKeyStoreName, tenantDomain); + } else { + privateKey = (PrivateKey) keyStoreManager.getPrivateKey(tenantKeyStoreName, + tenantDomain + + IdentityKeyStoreResolverConstants.KEY_STORE_CONTEXT_SEPARATOR + context); + } } catch (IdentityException e) { - throw new SignatureException("Error while signing from private key of tenant: " + tenantDomain, e); + throw new SignatureException("Error while retrieving the private key for tenant: " + tenantDomain, e); } } + + // Sign the data with the retrieved private key return SignatureUtil.doSignature(data, privateKey); } + + /** + * Sign the given data for the specified tenant domain. + * + * @param data The data to be signed. + * @param tenantDomain The tenant domain to which the data belongs. + * @return The signature of the data. + * @throws SignatureException If an error occurs during the signature generation process. + */ + public static byte[] signWithTenantKey(String data, String tenantDomain) throws SignatureException { + + return signWithTenantKey(data, tenantDomain, null); + } } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolverTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolverTest.java index 52abb6a18591..4246e1eaaf14 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolverTest.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/IdentityKeyStoreResolverTest.java @@ -30,6 +30,7 @@ import org.wso2.carbon.identity.core.util.IdentityConfigParser; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import org.wso2.carbon.utils.security.KeystoreUtils; import java.io.FileInputStream; import java.lang.reflect.Field; @@ -84,6 +85,7 @@ public class IdentityKeyStoreResolverTest extends TestCase { private MockedStatic identityConfigParser; private MockedStatic identityTenantUtil; + private MockedStatic keystoreUtils; private IdentityKeyStoreResolver identityKeyStoreResolver; @@ -143,6 +145,7 @@ public void setUp() throws Exception { when(keyStoreManager.getCertificate("CUSTOM/" + CUSTOM_KEY_STORE, null)).thenReturn(customCertificate); identityKeyStoreResolver = IdentityKeyStoreResolver.getInstance(); + keystoreUtils = mockStatic(KeystoreUtils.class); } @AfterClass @@ -150,6 +153,7 @@ public void close() { identityConfigParser.close(); identityTenantUtil.close(); + keystoreUtils.close(); } @Test @@ -210,6 +214,7 @@ public Object[][] keyStoreDataProvider() { @Test(dataProvider = "KeyStoreDataProvider") public void testGetKeyStore(String tenantDomain, InboundProtocol inboundProtocol, KeyStore expectedKeyStore) throws Exception { + keystoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension(tenantDomain)).thenReturn(".jks"); assertEquals(expectedKeyStore, identityKeyStoreResolver.getKeyStore(tenantDomain, inboundProtocol)); } @@ -229,6 +234,7 @@ public Object[][] privateKeyDataProvider() { @Test(dataProvider = "PrivateKeyDataProvider") public void testGetPrivateKey(String tenantDomain, InboundProtocol inboundProtocol, PrivateKey expectedKey) throws Exception { + keystoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension(tenantDomain)).thenReturn(".jks"); assertEquals(expectedKey, identityKeyStoreResolver.getPrivateKey(tenantDomain, inboundProtocol)); } @@ -248,6 +254,7 @@ public Object[][] publicCertificateDataProvider() { @Test(dataProvider = "PublicCertificateDataProvider") public void testGetCertificate(String tenantDomain, InboundProtocol inboundProtocol, X509Certificate expectedCert) throws Exception { + keystoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension(tenantDomain)).thenReturn(".jks"); assertEquals(expectedCert, identityKeyStoreResolver.getCertificate(tenantDomain, inboundProtocol)); } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtilTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtilTest.java index 0a3d7eb3faf1..98d094f26871 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtilTest.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityKeyStoreResolverUtilTest.java @@ -18,9 +18,14 @@ package org.wso2.carbon.identity.core.util; +import org.mockito.MockedStatic; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.wso2.carbon.utils.security.KeystoreUtils; +import static org.mockito.Mockito.mockStatic; import static org.testng.Assert.assertEquals; import static org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverUtil.buildCustomKeyStoreName; @@ -34,6 +39,14 @@ */ public class IdentityKeyStoreResolverUtilTest { + private MockedStatic keystoreUtils; + + @BeforeClass + public void setUp() throws Exception { + + keystoreUtils = mockStatic(KeystoreUtils.class); + } + @DataProvider(name = "CorrectTenantKeyStoreNameDataProvider") public Object[][] correctTenantKeyStoreNameDataProvider() { @@ -43,10 +56,17 @@ public Object[][] correctTenantKeyStoreNameDataProvider() { }; } + @AfterClass + public void close() { + + keystoreUtils.close(); + } + @Test(dataProvider = "CorrectTenantKeyStoreNameDataProvider") public void testCorrectBuildTenantKeyStoreName(String tenantDomain, String expectedResult) throws IdentityKeyStoreResolverException { - assertEquals(expectedResult, buildTenantKeyStoreName(tenantDomain)); + keystoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension(tenantDomain)).thenReturn(".jks"); + assertEquals(buildTenantKeyStoreName(tenantDomain), expectedResult); } @DataProvider(name = "IncorrectTenantKeyStoreNameDataProvider") diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityUtilTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityUtilTest.java index 4aeb8af2cf83..cd833299e972 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityUtilTest.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/IdentityUtilTest.java @@ -56,6 +56,7 @@ import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.ConfigurationContextService; import org.wso2.carbon.utils.NetworkUtils; +import org.wso2.carbon.utils.security.KeystoreUtils; import java.io.FileInputStream; import java.io.IOException; @@ -96,6 +97,8 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; +import static org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE; +import static org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants.ErrorMessages.ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST; @Listeners(MockitoTestNGListener.class) public class IdentityUtilTest { @@ -150,6 +153,7 @@ public class IdentityUtilTest { MockedStatic signatureUtil; MockedStatic identityKeyStoreResolver; MockedStatic keyStoreManager; + private MockedStatic keystoreUtils; @BeforeMethod @@ -164,6 +168,7 @@ public void setUp() throws Exception { signatureUtil = mockStatic(SignatureUtil.class); identityKeyStoreResolver = mockStatic(IdentityKeyStoreResolver.class); keyStoreManager = mockStatic(KeyStoreManager.class); + keystoreUtils = mockStatic(KeystoreUtils.class); serverConfiguration.when(ServerConfiguration::getInstance).thenReturn(mockServerConfiguration); identityCoreServiceComponent.when( @@ -203,6 +208,7 @@ public void tearDown() throws Exception { signatureUtil.close(); identityKeyStoreResolver.close(); keyStoreManager.close(); + keystoreUtils.close(); } @Test(description = "Test converting a certificate to PEM format") @@ -1110,12 +1116,69 @@ public void testValidateSignatureFromTenant() throws Exception { assertTrue(result); } + @Test + public void testValidateSignatureFromContextKeystore() throws Exception { + + String data = "testData"; + byte[] signature = new byte[]{1, 2, 3}; + String tenantDomain = "carbon.super"; + String context = "cookie"; + + when(mockCertificate.getPublicKey()).thenReturn(mockPublicKey); + identityKeyStoreResolver.when(IdentityKeyStoreResolver::getInstance).thenReturn(mockIdentityKeyStoreResolver); + when(mockIdentityKeyStoreResolver.getCertificate(tenantDomain, null, context)).thenReturn(mockCertificate); + signatureUtil.when(() -> SignatureUtil.validateSignature(data, signature, mockPublicKey)).thenReturn(true); + + boolean result = IdentityUtil.validateSignatureFromTenant(data, signature, tenantDomain, context); + assertTrue(result); + } + + @Test(description = "Validate signature when the context keystore does not exist. " + + "Expect the method to return false without throwing an exception.") + public void testValidateSignatureFromContextKeystoreIfNotExists() throws Exception { + + String data = "testData"; + byte[] signature = new byte[]{1, 2, 3}; + String tenantDomain = "carbon.super"; + String context = "cookie"; + + identityKeyStoreResolver.when(IdentityKeyStoreResolver::getInstance).thenReturn(mockIdentityKeyStoreResolver); + when(mockIdentityKeyStoreResolver.getCertificate(tenantDomain, null, context)) + .thenThrow(new IdentityKeyStoreResolverException + (ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST.getCode(), + ERROR_RETRIEVING_TENANT_CONTEXT_PUBLIC_CERTIFICATE_KEYSTORE_NOT_EXIST.getDescription())); + signatureUtil.when(() -> SignatureUtil.validateSignature(data, signature, mockPublicKey)).thenReturn(true); + + boolean result = IdentityUtil.validateSignatureFromTenant(data, signature, tenantDomain, context); + assertFalse(result); + } + + @Test(description = "Validate signature when an unexpected exception occurs while retrieving the " + + "tenant's public certificate. Expect a SignatureException to be thrown.", + expectedExceptions = SignatureException.class) + public void testValidateSignatureFromContextKeystoreNegative() throws Exception { + + String data = "testData"; + byte[] signature = new byte[]{1, 2, 3}; + String tenantDomain = "carbon.super"; + String context = "cookie"; + + identityKeyStoreResolver.when(IdentityKeyStoreResolver::getInstance).thenReturn(mockIdentityKeyStoreResolver); + when(mockIdentityKeyStoreResolver.getCertificate(tenantDomain, null, context)) + .thenThrow(new IdentityKeyStoreResolverException + (ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE.getCode(), + ERROR_CODE_ERROR_RETRIEVING_TENANT_PUBLIC_CERTIFICATE.getDescription())); + + IdentityUtil.validateSignatureFromTenant(data, signature, tenantDomain, context); + } + @Test public void testSignWithTenantKey() throws Exception { String data = "testData"; String superTenantDomain = "carbon.super"; keyStoreManager.when(() -> KeyStoreManager.getInstance(anyInt())).thenReturn(mockKeyStoreManager); + keystoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension(superTenantDomain)).thenReturn(".jks"); when(mockKeyStoreManager.getDefaultPrivateKey()).thenReturn(mockPrivateKey); when(mockKeyStoreManager.getPrivateKey(anyString(), anyString())).thenReturn(mockPrivateKey); diff --git a/components/identity-core/pom.xml b/components/identity-core/pom.xml index cf5889fed334..36446c26090f 100644 --- a/components/identity-core/pom.xml +++ b/components/identity-core/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/identity-event/org.wso2.carbon.identity.event/pom.xml b/components/identity-event/org.wso2.carbon.identity.event/pom.xml index 01f774495e88..d2cce7f781ab 100644 --- a/components/identity-event/org.wso2.carbon.identity.event/pom.xml +++ b/components/identity-event/org.wso2.carbon.identity.event/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-event - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/identity-event/pom.xml b/components/identity-event/pom.xml index e882af14f55e..9066b8262ae7 100644 --- a/components/identity-event/pom.xml +++ b/components/identity-event/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/pom.xml b/components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/pom.xml index c02272c3c872..b0c1eedd38b5 100644 --- a/components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/pom.xml +++ b/components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/identity-mgt/org.wso2.carbon.identity.mgt.ui/pom.xml b/components/identity-mgt/org.wso2.carbon.identity.mgt.ui/pom.xml index 2f1f80c4cdba..35e4fda64e52 100644 --- a/components/identity-mgt/org.wso2.carbon.identity.mgt.ui/pom.xml +++ b/components/identity-mgt/org.wso2.carbon.identity.mgt.ui/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework identity-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/identity-mgt/org.wso2.carbon.identity.mgt/pom.xml b/components/identity-mgt/org.wso2.carbon.identity.mgt/pom.xml index 92717840887b..72c8f89a88a7 100644 --- a/components/identity-mgt/org.wso2.carbon.identity.mgt/pom.xml +++ b/components/identity-mgt/org.wso2.carbon.identity.mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/identity-mgt/pom.xml b/components/identity-mgt/pom.xml index 594e1971e6ff..bd43fe98ca9b 100644 --- a/components/identity-mgt/pom.xml +++ b/components/identity-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt.ui/pom.xml b/components/idp-mgt/org.wso2.carbon.idp.mgt.ui/pom.xml index 41a586394233..c975ea4dde5b 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt.ui/pom.xml +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-provider-management - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/pom.xml b/components/idp-mgt/org.wso2.carbon.idp.mgt/pom.xml index 8186e034f9e6..b957471dd844 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/pom.xml +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-provider-management - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementFacade.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementFacade.java index 8d342de4299d..d81da034e0ab 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementFacade.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementFacade.java @@ -311,7 +311,7 @@ public List getAllUserDefinedFederatedAuthenticato } private IdentityProvider populateEndpointConfig(IdentityProvider identityProvider, String tenantDomain) - throws IdentityProviderManagementServerException { + throws IdentityProviderManagementException { if (identityProvider == null || identityProvider.getFederatedAuthenticatorConfigs().length != 1) { return identityProvider; @@ -322,7 +322,7 @@ private IdentityProvider populateEndpointConfig(IdentityProvider identityProvide } private void addEndpointConfig(IdentityProvider identityProvider, String tenantDomain) - throws IdentityProviderManagementServerException { + throws IdentityProviderManagementException { if (identityProvider == null || identityProvider.getFederatedAuthenticatorConfigs().length != 1) { return; @@ -333,7 +333,7 @@ private void addEndpointConfig(IdentityProvider identityProvider, String tenantD private void updateEndpointConfig(IdentityProvider newIdentityProvider, IdentityProvider oldIdentityProvider, String tenantDomain) - throws IdentityProviderManagementServerException { + throws IdentityProviderManagementException { if (newIdentityProvider == null || newIdentityProvider.getFederatedAuthenticatorConfigs().length != 1) { return; @@ -354,7 +354,7 @@ private void updateEndpointConfig(IdentityProvider newIdentityProvider, Identity } private void deleteEndpointConfig(IdentityProvider identityProvider, String tenantDomain) - throws IdentityProviderManagementServerException { + throws IdentityProviderManagementException { if (identityProvider == null || identityProvider.getFederatedAuthenticatorConfigs().length != 1) { return; diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/UserDefinedAuthenticatorEndpointConfigManager.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/UserDefinedAuthenticatorEndpointConfigManager.java index e0d8e656ace0..0c10c854c771 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/UserDefinedAuthenticatorEndpointConfigManager.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/UserDefinedAuthenticatorEndpointConfigManager.java @@ -18,6 +18,7 @@ package org.wso2.carbon.idp.mgt.util; +import org.wso2.carbon.identity.action.management.exception.ActionMgtClientException; import org.wso2.carbon.identity.action.management.exception.ActionMgtException; import org.wso2.carbon.identity.action.management.model.Action; import org.wso2.carbon.identity.action.management.model.EndpointConfig; @@ -26,6 +27,8 @@ import org.wso2.carbon.identity.application.common.model.UserDefinedAuthenticatorEndpointConfig; import org.wso2.carbon.identity.application.common.model.UserDefinedFederatedAuthenticatorConfig; import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants; +import org.wso2.carbon.idp.mgt.IdentityProviderManagementClientException; +import org.wso2.carbon.idp.mgt.IdentityProviderManagementException; import org.wso2.carbon.idp.mgt.IdentityProviderManagementServerException; import org.wso2.carbon.idp.mgt.internal.IdpMgtServiceComponentHolder; import org.wso2.carbon.idp.mgt.util.IdPManagementConstants.ErrorMessage; @@ -50,7 +53,7 @@ public class UserDefinedAuthenticatorEndpointConfigManager { * @throws IdentityProviderManagementServerException If an error occurs while adding the action. */ public void addEndpointConfig(FederatedAuthenticatorConfig config, String tenantDomain) - throws IdentityProviderManagementServerException { + throws IdentityProviderManagementException { if (config.getDefinedByType() != AuthenticatorPropertyConstants.DefinedByType.USER) { return; @@ -69,9 +72,7 @@ public void addEndpointConfig(FederatedAuthenticatorConfig config, String tenant endpointProperty.setConfidential(false); config.setProperties(new Property[]{endpointProperty}); } catch (ActionMgtException e) { - ErrorMessage error = ErrorMessage.ERROR_CODE_ADDING_ENDPOINT_CONFIG; - throw new IdentityProviderManagementServerException(error.getCode(), String.format(error.getMessage(), - config.getName()), e); + throw handleActionMgtException(ErrorMessage.ERROR_CODE_ADDING_ENDPOINT_CONFIG, e, config.getName()); } } @@ -84,7 +85,7 @@ public void addEndpointConfig(FederatedAuthenticatorConfig config, String tenant * @throws IdentityProviderManagementServerException If an error occurs while updating associated action. */ public void updateEndpointConfig(FederatedAuthenticatorConfig newConfig, FederatedAuthenticatorConfig oldConfig, - String tenantDomain) throws IdentityProviderManagementServerException { + String tenantDomain) throws IdentityProviderManagementException { if (oldConfig.getDefinedByType() != AuthenticatorPropertyConstants.DefinedByType.USER) { return; @@ -100,9 +101,7 @@ public void updateEndpointConfig(FederatedAuthenticatorConfig newConfig, Federat tenantDomain); newConfig.setProperties(oldConfig.getProperties()); } catch (ActionMgtException e) { - ErrorMessage error = ErrorMessage.ERROR_CODE_UPDATING_ENDPOINT_CONFIG; - throw new IdentityProviderManagementServerException(error.getCode(), String.format(error.getMessage(), - newConfig.getName()), e); + throw handleActionMgtException(ErrorMessage.ERROR_CODE_UPDATING_ENDPOINT_CONFIG, e, newConfig.getName()); } } @@ -115,7 +114,7 @@ public void updateEndpointConfig(FederatedAuthenticatorConfig newConfig, Federat * @throws IdentityProviderManagementServerException If an error occurs retrieving updating associated action. */ public FederatedAuthenticatorConfig resolveEndpointConfig(FederatedAuthenticatorConfig config, - String tenantDomain) throws IdentityProviderManagementServerException { + String tenantDomain) throws IdentityProviderManagementException { if (config.getDefinedByType() != AuthenticatorPropertyConstants.DefinedByType.USER) { return config; @@ -132,9 +131,7 @@ public FederatedAuthenticatorConfig resolveEndpointConfig(FederatedAuthenticator castedConfig.setEndpointConfig(buildUserDefinedAuthenticatorEndpointConfig(action.getEndpoint())); return castedConfig; } catch (ActionMgtException e) { - ErrorMessage error = ErrorMessage.ERROR_CODE_RETRIEVING_ENDPOINT_CONFIG; - throw new IdentityProviderManagementServerException(error.getCode(), String.format(error.getMessage(), - config.getName()), e); + throw handleActionMgtException(ErrorMessage.ERROR_CODE_RETRIEVING_ENDPOINT_CONFIG, e, config.getName()); } } @@ -160,7 +157,7 @@ private UserDefinedAuthenticatorEndpointConfig buildUserDefinedAuthenticatorEndp * @throws IdentityProviderManagementServerException If an error occurs while deleting associated action. */ public void deleteEndpointConfig(FederatedAuthenticatorConfig config, String tenantDomain) throws - IdentityProviderManagementServerException { + IdentityProviderManagementException { if (config.getDefinedByType() != AuthenticatorPropertyConstants.DefinedByType.USER) { return; @@ -173,9 +170,7 @@ public void deleteEndpointConfig(FederatedAuthenticatorConfig config, String ten actionId, tenantDomain); } catch (ActionMgtException e) { - ErrorMessage error = ErrorMessage.ERROR_CODE_DELETING_ENDPOINT_CONFIG; - throw new IdentityProviderManagementServerException(error.getCode(), String.format(error.getMessage(), - config.getName()), e); + throw handleActionMgtException(ErrorMessage.ERROR_CODE_DELETING_ENDPOINT_CONFIG, e, config.getName()); } } @@ -209,4 +204,18 @@ private String getActionIdFromProperty(Property[] properties, String authenticat "No action Id was found in the properties of the authenticator configurations for the " + "authenticator: " + authenticatorName)); } + + private static IdentityProviderManagementClientException handleActionMgtException(ErrorMessage idpMgtError, + Throwable actionException, String... data) + throws IdentityProviderManagementException { + + if (actionException instanceof ActionMgtClientException) { + ActionMgtClientException error = (ActionMgtClientException) actionException; + throw new IdentityProviderManagementClientException( + idpMgtError.getCode(), idpMgtError.getMessage(), error.getDescription()); + } + + throw new IdentityProviderManagementServerException(idpMgtError.getCode(), + String.format(idpMgtError.getMessage(), data), actionException); + } } diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/test/java/org/wso2/carbon/idp/mgt/IdentityProviderManagementServiceTest.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/test/java/org/wso2/carbon/idp/mgt/IdentityProviderManagementServiceTest.java index be164abfdf08..870c9f6890e9 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/test/java/org/wso2/carbon/idp/mgt/IdentityProviderManagementServiceTest.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/test/java/org/wso2/carbon/idp/mgt/IdentityProviderManagementServiceTest.java @@ -27,7 +27,8 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.wso2.carbon.core.util.CryptoUtil; -import org.wso2.carbon.identity.action.management.exception.ActionMgtException; +import org.wso2.carbon.identity.action.management.exception.ActionMgtClientException; +import org.wso2.carbon.identity.action.management.exception.ActionMgtServerException; import org.wso2.carbon.identity.action.management.model.Action; import org.wso2.carbon.identity.action.management.model.EndpointConfig; import org.wso2.carbon.identity.action.management.service.ActionManagementService; @@ -262,10 +263,23 @@ public void testAddIdPActionException() throws Exception { ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); when(actionManagementServiceForException.addAction(anyString(), any(), any())) - .thenThrow(ActionMgtException.class); + .thenThrow(ActionMgtServerException.class); IdpMgtServiceComponentHolder.getInstance().setActionManagementService(actionManagementServiceForException); - assertThrows(IdentityProviderManagementException.class, () -> + assertThrows(IdentityProviderManagementServerException.class, () -> + identityProviderManagementService.addIdP(idpForErrorScenarios)); + identityProviderManagementService.getIdPByName(idpForErrorScenarios.getIdentityProviderName()); + } + + @Test + public void testAddIdPActionClientException() throws Exception { + + ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); + when(actionManagementServiceForException.addAction(anyString(), any(), any())) + .thenThrow(ActionMgtClientException.class); + IdpMgtServiceComponentHolder.getInstance().setActionManagementService(actionManagementServiceForException); + + assertThrows(IdentityProviderManagementClientException.class, () -> identityProviderManagementService.addIdP(idpForErrorScenarios)); identityProviderManagementService.getIdPByName(idpForErrorScenarios.getIdentityProviderName()); } @@ -625,11 +639,12 @@ public void testDeleteIdPActionException() throws Exception { identityProviderManagementService.addIdP(userDefinedIdP); ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); - doThrow(ActionMgtException.class).when(actionManagementServiceForException).deleteAction(any(), any(), any()); + doThrow(ActionMgtServerException.class).when(actionManagementServiceForException) + .deleteAction(any(), any(), any()); when(actionManagementServiceForException.getActionByActionId(anyString(), any(), any())).thenReturn(action); IdpMgtServiceComponentHolder.getInstance().setActionManagementService(actionManagementServiceForException); - assertThrows(IdentityProviderManagementException.class, () -> + assertThrows(IdentityProviderManagementServerException.class, () -> identityProviderManagementService.deleteIdP(userDefinedIdP.getIdentityProviderName())); Assert.assertNotNull(identityProviderManagementService.getIdPByName(userDefinedIdP .getIdentityProviderName())); @@ -742,7 +757,7 @@ public void testUpdateIdPActionException() throws Exception { ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); when(actionManagementServiceForException.updateAction(any(), any(), any(), any())) - .thenThrow(ActionMgtException.class); + .thenThrow(ActionMgtServerException.class); when(actionManagementServiceForException.getActionByActionId(anyString(), any(), any())).thenReturn(action); IdpMgtServiceComponentHolder.getInstance().setActionManagementService(actionManagementServiceForException); @@ -900,11 +915,11 @@ public void testGetIdPActionException() throws Exception { ActionManagementService actionManagementServiceForException = mock(ActionManagementService.class); when(actionManagementServiceForException.addAction(anyString(), any(), any())).thenReturn(action); when(actionManagementServiceForException.getActionByActionId(anyString(), any(), any())) - .thenThrow(ActionMgtException.class); + .thenThrow(ActionMgtServerException.class); IdpMgtServiceComponentHolder.getInstance().setActionManagementService(actionManagementServiceForException); - IdentityProviderManagementException error = assertThrows(IdentityProviderManagementException.class, () -> - identityProviderManagementService.addIdP(idpForErrorScenarios)); + IdentityProviderManagementServerException error = assertThrows(IdentityProviderManagementServerException.class, + () -> identityProviderManagementService.addIdP(idpForErrorScenarios)); assertEquals(error.getErrorCode(), ErrorMessage.ERROR_CODE_RETRIEVING_ENDPOINT_CONFIG.getCode()); } diff --git a/components/idp-mgt/pom.xml b/components/idp-mgt/pom.xml index 15f282175c95..18428610ff7d 100644 --- a/components/idp-mgt/pom.xml +++ b/components/idp-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt/pom.xml b/components/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt/pom.xml index 72c7a6547136..a5a34deaf1cf 100644 --- a/components/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt/pom.xml +++ b/components/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework input-validation-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/input-validation-mgt/pom.xml b/components/input-validation-mgt/pom.xml index 751aaefe2261..6d30c9e9099c 100644 --- a/components/input-validation-mgt/pom.xml +++ b/components/input-validation-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt/pom.xml b/components/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt/pom.xml index 93c771787e50..d9b630f6d53c 100644 --- a/components/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt/pom.xml +++ b/components/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt/pom.xml @@ -21,7 +21,7 @@ multi-attribute-login org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt/pom.xml b/components/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt/pom.xml index d628487b40aa..9d3bf52c7e88 100644 --- a/components/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt/pom.xml +++ b/components/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt/pom.xml @@ -21,7 +21,7 @@ multi-attribute-login org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/multi-attribute-login/pom.xml b/components/multi-attribute-login/pom.xml index fa0ea5eed63d..63db13cfd4ef 100644 --- a/components/multi-attribute-login/pom.xml +++ b/components/multi-attribute-login/pom.xml @@ -21,7 +21,7 @@ identity-framework org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/components/notification-mgt/org.wso2.carbon.identity.notification.mgt/pom.xml b/components/notification-mgt/org.wso2.carbon.identity.notification.mgt/pom.xml index 8670e2d8a6c8..e5bbf1e1c7b9 100644 --- a/components/notification-mgt/org.wso2.carbon.identity.notification.mgt/pom.xml +++ b/components/notification-mgt/org.wso2.carbon.identity.notification.mgt/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework notification-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/notification-mgt/pom.xml b/components/notification-mgt/pom.xml index 4257e2f6e504..99b3e090bc2b 100644 --- a/components/notification-mgt/pom.xml +++ b/components/notification-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml b/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml index 15a970f13011..6d9252dd8d35 100644 --- a/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml +++ b/components/provisioning/org.wso2.carbon.identity.provisioning/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework provisioning - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/provisioning/pom.xml b/components/provisioning/pom.xml index b89e6a3d7edf..889e2f84105e 100644 --- a/components/provisioning/pom.xml +++ b/components/provisioning/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/role-mgt/org.wso2.carbon.identity.role.mgt.core/pom.xml b/components/role-mgt/org.wso2.carbon.identity.role.mgt.core/pom.xml index ff53d1f23d77..d77e64d6bd10 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.mgt.core/pom.xml +++ b/components/role-mgt/org.wso2.carbon.identity.role.mgt.core/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework role-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/pom.xml b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/pom.xml index de70aeadd36d..01ca99b2a619 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/pom.xml +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework role-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleConstants.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleConstants.java index 6a171b953e2a..3773d21edfe1 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleConstants.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleConstants.java @@ -80,6 +80,12 @@ private RoleConstants() { public static final String NEW_ROLE_NAME = "newRoleName"; public static final String FAILURE_REASON = "failureReason"; + // Role management service configurations. + public static final String ALLOW_SYSTEM_PREFIX_FOR_ROLES = "RoleMgt.AllowSystemPrefixForRoles"; + + // Role properties + public static final String IS_SHARED_ROLE_PROP_NAME = "isSharedRole"; + /** * Grouping of constants related to database table names. */ diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImpl.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImpl.java index 4148f2dbe0dc..85bfab183292 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImpl.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImpl.java @@ -49,6 +49,7 @@ import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleDTO; import org.wso2.carbon.identity.role.v2.mgt.core.model.UserBasicInfo; +import org.wso2.carbon.identity.role.v2.mgt.core.util.RoleManagementUtils; import org.wso2.carbon.identity.role.v2.mgt.core.util.UserIDResolver; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; @@ -75,70 +76,79 @@ public class RoleManagementServiceImpl implements RoleManagementService { private static final Log log = LogFactory.getLog(RoleManagementServiceImpl.class); private final RoleDAO roleDAO = RoleMgtDAOFactory.getInstance().getRoleDAO(); private final UserIDResolver userIDResolver = new UserIDResolver(); + private static final String IS_FRAGMENT_APP = "isFragmentApp"; @Override public RoleBasicInfo addRole(String roleName, List userList, List groupList, List permissions, String audience, String audienceId, String tenantDomain) throws IdentityRoleManagementException { - if (StringUtils.startsWithIgnoreCase(roleName, UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX)) { - String errorMessage = String.format("Invalid role name: %s. Role names with the prefix: %s, is not allowed" - + " to be created from externally in the system.", roleName, - UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX); - throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), errorMessage); - } - if (isDomainSeparatorPresent(roleName)) { - // SCIM2 API only adds roles to the internal domain. - throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), "Invalid character: " - + UserCoreConstants.DOMAIN_SEPARATOR + " contains in the role name: " + roleName + "."); - } - List roleManagementListenerList = RoleManagementServiceComponentHolder.getInstance() - .getRoleManagementListenerList(); - for (RoleManagementListener roleManagementListener : roleManagementListenerList) { - if (roleManagementListener.isEnable()) { - roleManagementListener.preAddRole(roleName, userList, groupList, - permissions, audience, audienceId, tenantDomain); + try { + if (!RoleManagementUtils.isAllowSystemPrefixForRole() && + StringUtils.startsWithIgnoreCase(roleName, UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX)) { + String errorMessage = String.format("Invalid role name: %s. Role names with the prefix: %s, is not " + + "allowed to be created from externally in the system.", roleName, + UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX); + throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), errorMessage); + } + if (isDomainSeparatorPresent(roleName)) { + // SCIM2 API only adds roles to the internal domain. + throw new IdentityRoleManagementClientException(INVALID_REQUEST.getCode(), "Invalid character: " + + UserCoreConstants.DOMAIN_SEPARATOR + " contains in the role name: " + roleName + "."); + } + List roleManagementListenerList = RoleManagementServiceComponentHolder. + getInstance().getRoleManagementListenerList(); + for (RoleManagementListener roleManagementListener : roleManagementListenerList) { + if (roleManagementListener.isEnable()) { + roleManagementListener.preAddRole(roleName, userList, groupList, + permissions, audience, audienceId, tenantDomain); + } } - } - RoleManagementEventPublisherProxy roleManagementEventPublisherProxy = RoleManagementEventPublisherProxy - .getInstance(); - roleManagementEventPublisherProxy.publishPreAddRoleWithException(roleName, userList, groupList, permissions, - audience, audienceId, tenantDomain); + RoleManagementEventPublisherProxy roleManagementEventPublisherProxy = RoleManagementEventPublisherProxy + .getInstance(); + roleManagementEventPublisherProxy.publishPreAddRoleWithException(roleName, userList, groupList, + permissions, audience, audienceId, tenantDomain); - // Validate audience. - if (StringUtils.isNotEmpty(audience)) { - if (!(ORGANIZATION.equalsIgnoreCase(audience) || APPLICATION.equalsIgnoreCase(audience))) { - throw new IdentityRoleManagementClientException(INVALID_AUDIENCE.getCode(), "Invalid role audience"); - } - if (ORGANIZATION.equalsIgnoreCase(audience)) { - validateOrganizationRoleAudience(audienceId, tenantDomain); + // Validate audience. + if (StringUtils.isNotEmpty(audience)) { + if (!(ORGANIZATION.equalsIgnoreCase(audience) || APPLICATION.equalsIgnoreCase(audience))) { + throw new IdentityRoleManagementClientException(INVALID_AUDIENCE.getCode(), + "Invalid role audience"); + } + if (ORGANIZATION.equalsIgnoreCase(audience)) { + validateOrganizationRoleAudience(audienceId, tenantDomain); + audience = ORGANIZATION; + } + if (APPLICATION.equalsIgnoreCase(audience)) { + // audience validation done using listener. + audience = APPLICATION; + } + } else { audience = ORGANIZATION; + audienceId = getOrganizationIdByTenantDomain(tenantDomain); + } + validatePermissions(permissions, audience, audienceId, tenantDomain); + RoleBasicInfo roleBasicInfo = roleDAO.addRole(roleName, userList, groupList, permissions, audience, + audienceId, tenantDomain); + roleManagementEventPublisherProxy.publishPostAddRole(roleBasicInfo.getId(), roleName, userList, groupList, + permissions, audience, audienceId, tenantDomain); + if (log.isDebugEnabled()) { + log.debug(String.format("%s added role of name : %s successfully.", getUser(tenantDomain), roleName)); + } + RoleBasicInfo role = roleDAO.getRoleBasicInfoById(roleBasicInfo.getId(), tenantDomain); + for (RoleManagementListener roleManagementListener : roleManagementListenerList) { + if (roleManagementListener.isEnable()) { + roleManagementListener.postAddRole(role, roleName, userList, + groupList, permissions, audience, audienceId, tenantDomain); + } } - if (APPLICATION.equalsIgnoreCase(audience)) { - // audience validation done using listener. - audience = APPLICATION; + return role; + } finally { + if (IdentityUtil.threadLocalProperties.get().get(IS_FRAGMENT_APP) != null) { + IdentityUtil.threadLocalProperties.get().remove(IS_FRAGMENT_APP); } - } else { - audience = ORGANIZATION; - audienceId = getOrganizationIdByTenantDomain(tenantDomain); } - validatePermissions(permissions, audience, audienceId, tenantDomain); - RoleBasicInfo roleBasicInfo = roleDAO.addRole(roleName, userList, groupList, permissions, audience, audienceId, - tenantDomain); - roleManagementEventPublisherProxy.publishPostAddRole(roleBasicInfo.getId(), roleName, userList, groupList, - permissions, audience, audienceId, tenantDomain); - if (log.isDebugEnabled()) { - log.debug(String.format("%s added role of name : %s successfully.", getUser(tenantDomain), roleName)); - } - RoleBasicInfo role = roleDAO.getRoleBasicInfoById(roleBasicInfo.getId(), tenantDomain); - for (RoleManagementListener roleManagementListener : roleManagementListenerList) { - if (roleManagementListener.isEnable()) { - roleManagementListener.postAddRole(role, roleName, userList, - groupList, permissions, audience, audienceId, tenantDomain); - } - } - return role; } @Override diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java index a7c12941f469..cfadce04c194 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java @@ -54,6 +54,7 @@ import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleAudience; import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleDTO; +import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleProperty; import org.wso2.carbon.identity.role.v2.mgt.core.model.UserBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.util.GroupIDResolver; import org.wso2.carbon.identity.role.v2.mgt.core.util.UserIDResolver; @@ -213,6 +214,8 @@ public class RoleDAOImpl implements RoleDAO { private static final String GROUPS = "groups"; private static final String PERMISSIONS = "permissions"; private static final String ASSOCIATED_APPLICATIONS = "associatedApplications"; + private static final String PROPERTIES = "properties"; + private static final String IS_FRAGMENT_APP = "isFragmentApp"; @Override public RoleBasicInfo addRole(String roleName, List userList, List groupList, @@ -465,6 +468,10 @@ private List getRolesRequestedAttributes(List roles, List permis addRoleID(roleId, roleName, audienceRefId, tenantDomain, connection); addPermissions(roleId, permissions, tenantDomain, connection); - if (APPLICATION.equals(audience) && !isOrganization(tenantDomain)) { + if (APPLICATION.equals(audience) && !isFragmentApp()) { addAppRoleAssociation(roleId, audienceId, connection); } IdentityDatabaseUtil.commitTransaction(connection); @@ -1666,6 +1689,23 @@ private void addRoleInfo(String roleId, String roleName, List permis } } + /** + * Check whether the corresponding application is a fragment application. This check is using a thread local + * property which is set from the default role management listener. + * + * @return True if the application is a fragment application. + */ + private boolean isFragmentApp() { + + if (IdentityUtil.threadLocalProperties.get().get(IS_FRAGMENT_APP) != null) { + boolean isFragmentApp = Boolean.parseBoolean(IdentityUtil.threadLocalProperties.get(). + get(IS_FRAGMENT_APP).toString()); + IdentityUtil.threadLocalProperties.get().remove(IS_FRAGMENT_APP); + return isFragmentApp; + } + return false; + } + @Override public boolean isSharedRole(String roleId, String tenantDomain) throws IdentityRoleManagementException { diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/Role.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/Role.java index 35f0dff15f57..fb907e520dba 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/Role.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/Role.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2023-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 @@ -18,6 +18,7 @@ package org.wso2.carbon.identity.role.v2.mgt.core.model; +import java.util.ArrayList; import java.util.List; /** @@ -37,6 +38,7 @@ public class Role { private String audienceId; private String audienceName; private List associatedApplications; + private List roleProperties = new ArrayList<>(); public Role() { @@ -281,4 +283,34 @@ public void setAssociatedApplications(List associatedAppl this.associatedApplications = associatedApplications; } + + /** + * Get the role properties. + * + * @return properties list of a role. + */ + public List getRoleProperties() { + + return roleProperties; + } + + /** + * Set the role properties. + * + * @param roleProperties properties list of a role. + */ + public void setRoleProperties(List roleProperties) { + + this.roleProperties = roleProperties; + } + + /** + * Set a role property to the role properties list. + * + * @param roleProperty a property of a role. + */ + public void setRoleProperty(RoleProperty roleProperty) { + + this.roleProperties.add(roleProperty); + } } diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/RoleProperty.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/RoleProperty.java new file mode 100644 index 000000000000..69a36fbaae02 --- /dev/null +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/model/RoleProperty.java @@ -0,0 +1,71 @@ +/* + * 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.role.v2.mgt.core.model; + +import java.io.Serializable; + +/** + * Role property object to store the role specific property details. + */ +public class RoleProperty implements Serializable { + + private static final long serialVersionUID = 1231265490501221547L; + private String name; + private String value; + + /** + * Get the value of the property. + * + * @return value. + */ + public String getValue() { + + return value; + } + + /** + * Set the value of the property. + * + * @param value Value of the property. + */ + public void setValue(String value) { + + this.value = value; + } + + /** + * Get the name of the property. + * + * @return Name (This is the key). + */ + public String getName() { + + return name; + } + + /** + * Set the name of the property. + * + * @param name (This is the key). + */ + public void setName(String name) { + + this.name = name; + } +} diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/util/RoleManagementUtils.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/util/RoleManagementUtils.java index 660a06784d9f..f8a02b874d4a 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/util/RoleManagementUtils.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/util/RoleManagementUtils.java @@ -21,6 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; +import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.dao.RoleDAO; import org.wso2.carbon.identity.role.v2.mgt.core.dao.RoleMgtDAOFactory; @@ -28,6 +29,8 @@ import java.util.Locale; +import static org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants.ALLOW_SYSTEM_PREFIX_FOR_ROLES; + /** * Util class for role management functionality. */ @@ -76,4 +79,15 @@ public static boolean isSharedRole(String roleId, String tenantDomain) throws Id return roleDAO.isSharedRole(roleId, tenantDomain); } + + /** + * Get the configuration to allow adding roles with the system_ prefix. This config should be enabled only if + * IS is used as a KM for APIM. + * + * @return True, if it is allowed to add roles with system_ prefix. + */ + public static boolean isAllowSystemPrefixForRole() { + + return Boolean.parseBoolean(IdentityUtil.getProperty(ALLOW_SYSTEM_PREFIX_FOR_ROLES)); + } } diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImplTest.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImplTest.java new file mode 100644 index 000000000000..8bea86eccb23 --- /dev/null +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/RoleManagementServiceImplTest.java @@ -0,0 +1,198 @@ +/* + * 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.role.v2.mgt.core; + +import org.apache.commons.lang.StringUtils; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.wso2.carbon.base.CarbonBaseConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.role.v2.mgt.core.dao.RoleDAO; +import org.wso2.carbon.identity.role.v2.mgt.core.dao.RoleMgtDAOFactory; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementClientException; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; +import org.wso2.carbon.identity.testutil.IdentityBaseTest; +import org.wso2.carbon.user.core.UserCoreConstants; + +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.anyList; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import static org.testng.AssertJUnit.assertEquals; +import static org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants.ALLOW_SYSTEM_PREFIX_FOR_ROLES; +import static org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants.APPLICATION; +import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; + +public class RoleManagementServiceImplTest extends IdentityBaseTest { + + @Mock + private RoleDAO roleDAO; + + private RoleManagementServiceImpl roleManagementService; + + private MockedStatic roleMgtDAOFactory; + private MockedStatic privilegedCarbonContext; + + private static final String USERNAME = "user"; + private static final String audienceId = "testId"; + private static final String roleId = "testRoleId"; + + private static MockedStatic roleManagementEventPublisherProxy; + + @BeforeClass + public static void setUpClass() throws Exception { + + roleManagementEventPublisherProxy = mockStatic(RoleManagementEventPublisherProxy.class); + } + + @BeforeMethod + public void setUp() { + + MockitoAnnotations.openMocks(this); + mockCarbonContextForTenant(); + + roleMgtDAOFactory = mockStatic(RoleMgtDAOFactory.class); + RoleMgtDAOFactory mockRoleMgtDAOFactory = mock(RoleMgtDAOFactory.class); + roleMgtDAOFactory.when(RoleMgtDAOFactory::getInstance) + .thenReturn(mockRoleMgtDAOFactory); + when(mockRoleMgtDAOFactory.getRoleDAO()).thenReturn(roleDAO); + + roleManagementService = new RoleManagementServiceImpl(); + } + + @AfterMethod + public void tearDown() throws Exception { + + privilegedCarbonContext.close(); + roleMgtDAOFactory.close(); + } + + @DataProvider(name = "addRoleWithSystemPrefixData") + public Object[][] addRoleWithSystemPrefixData() { + + return new Object[][]{ + {false, "testRole", false}, + {false, "system_testRole", true}, + {true, "testRole", false}, + {true, "system_testRole", false}, + }; + } + + @Test(dataProvider = "addRoleWithSystemPrefixData") + public void testAddRoleWithSystemPrefix(boolean allowSystemPrefix, String roleName, boolean errorScenario) + throws IdentityRoleManagementException { + + try (MockedStatic identityUtil = mockStatic(IdentityUtil.class)) { + identityUtil.when(() -> IdentityUtil.getProperty(ALLOW_SYSTEM_PREFIX_FOR_ROLES)) + .thenReturn(String.valueOf(allowSystemPrefix)); + + RoleBasicInfo mockRoleBasicInfo = new RoleBasicInfo(roleId, roleName); + mockRoleBasicInfo.setAudience(APPLICATION); + when(roleDAO.addRole(anyString(), anyList(), anyList(), anyList(), anyString(), anyString(), anyString())) + .thenReturn(mockRoleBasicInfo); + when(roleDAO.getRoleBasicInfoById(anyString(), anyString())).thenReturn(mockRoleBasicInfo); + + RoleManagementEventPublisherProxy mockRoleMgtEventPublisherProxy = mock( + RoleManagementEventPublisherProxy.class); + roleManagementEventPublisherProxy.when(RoleManagementEventPublisherProxy::getInstance) + .thenReturn(mockRoleMgtEventPublisherProxy); + lenient().doNothing().when(mockRoleMgtEventPublisherProxy).publishPreAddRoleWithException(anyString(), + anyList(), anyList(), anyList(), anyString(), anyString(), anyString()); + lenient().doNothing().when(mockRoleMgtEventPublisherProxy).publishPostAddRole(anyString(), anyString(), + anyList(), anyList(), anyList(), anyString(), anyString(), anyString()); + + RoleBasicInfo addedRole = roleManagementService.addRole(roleName, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), APPLICATION, audienceId, SUPER_TENANT_DOMAIN_NAME); + if (errorScenario) { + fail("An exception should have been thrown."); + } + assertNotNull(addedRole, "Role should have been added successfully."); + + } catch (IdentityRoleManagementClientException e) { + if (errorScenario) { + assertTrue(StringUtils.contains(e.getMessage(), String.format("Role names with the prefix: %s, " + + "is not allowed", UserCoreConstants.INTERNAL_SYSTEM_ROLE_PREFIX))); + } else { + fail("An exception should not have been thrown."); + } + } + } + + @Test + public void testAddRoleWithIsFragmentAppProperty() throws Exception { + + String roleName = "validRole"; + String audience = "APPLICATION"; + String audienceId = "application_id_01"; + String tenantDomain = "tenantDomain"; + + Map mockThreadLocalProperties = new HashMap<>(); + mockThreadLocalProperties.put("isFragmentApp", Boolean.TRUE.toString()); + IdentityUtil.threadLocalProperties.set(mockThreadLocalProperties); + + RoleBasicInfo expectedRole = new RoleBasicInfo("roleId", roleName); + when(roleDAO.addRole(anyString(), anyList(), anyList(), anyList(), anyString(), anyString(), anyString())) + .thenReturn(expectedRole); + + when(roleDAO.getRoleBasicInfoById(anyString(), anyString())).thenReturn(expectedRole); + + RoleManagementEventPublisherProxy mockRoleMgtEventPublisherProxy = mock( + RoleManagementEventPublisherProxy.class); + roleManagementEventPublisherProxy.when(RoleManagementEventPublisherProxy::getInstance) + .thenReturn(mockRoleMgtEventPublisherProxy); + lenient().doNothing().when(mockRoleMgtEventPublisherProxy).publishPreAddRoleWithException(anyString(), + anyList(), anyList(), anyList(), anyString(), anyString(), anyString()); + lenient().doNothing().when(mockRoleMgtEventPublisherProxy).publishPostAddRole(anyString(), anyString(), + anyList(), anyList(), anyList(), anyString(), anyString(), anyString()); + + RoleBasicInfo result = roleManagementService.addRole(roleName, new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), audience, audienceId, tenantDomain); + + assertEquals(expectedRole, result); + } + + private void mockCarbonContextForTenant() { + + String carbonHome = Paths.get(System.getProperty("user.dir"), "target", "test-classes").toString(); + System.setProperty(CarbonBaseConstants.CARBON_HOME, carbonHome); + + privilegedCarbonContext = mockStatic(PrivilegedCarbonContext.class); + PrivilegedCarbonContext mockPrivilegedCarbonContext = mock(PrivilegedCarbonContext.class); + privilegedCarbonContext.when(PrivilegedCarbonContext::getThreadLocalCarbonContext) + .thenReturn(mockPrivilegedCarbonContext); + when(mockPrivilegedCarbonContext.getUsername()).thenReturn(USERNAME); + } +} diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOTest.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOTest.java index 7c130f5d7b0f..c50c08ef8494 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOTest.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOTest.java @@ -52,6 +52,7 @@ import org.wso2.carbon.identity.role.v2.mgt.core.internal.RoleManagementServiceComponentHolder; import org.wso2.carbon.identity.role.v2.mgt.core.model.IdpGroup; import org.wso2.carbon.identity.role.v2.mgt.core.model.Permission; +import org.wso2.carbon.identity.role.v2.mgt.core.model.Role; import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.model.UserBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.util.GroupIDResolver; @@ -127,6 +128,11 @@ public class RoleDAOTest { private static final String UPDATED_SHARED_ORG_ROLE_NAME = "new-sharing-org-role-001"; private static final String SUB_ORG_ROLE_NAME = "sub-org-role-200"; private static final String MOCKED_EXCEPTION = "Mocked Exception"; + private static final String ROLE_PROPERTIES = "properties"; + private static final String IS_SHARED_ROLE = "isSharedRole"; + private static final String IS_FRAGMENT_APP = "isFragmentApp"; + private static final String SHARED_APP_ROLE_NAME = "shared-app-role-name-01"; + private static final String SHARED_APP_ID = "shared-app-id"; private static Map dataSourceMap = new HashMap<>(); private List userNamesList = new ArrayList<>(); @@ -242,6 +248,33 @@ public void testAddAppRole() throws Exception { SAMPLE_TENANT_DOMAIN)); } + @Test + public void testAddAppRoleToFragmentApp() throws Exception { + + RoleDAOImpl roleDAO = spy(new RoleDAOImpl()); + mockCacheClearing(roleDAO); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getUserDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityUtil.when(IdentityUtil::getPrimaryDomainName).thenReturn(USER_DOMAIN_PRIMARY); + identityUtil.when(() -> IdentityUtil.extractDomainFromName(anyString())).thenCallRealMethod(); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(anyString())).thenReturn(SAMPLE_TENANT_ID); + // Mock the threadLocalProperties static variable. + Map mockThreadLocalProperties = new HashMap<>(); + mockThreadLocalProperties.put(IS_FRAGMENT_APP, Boolean.TRUE.toString()); + IdentityUtil.threadLocalProperties.set(mockThreadLocalProperties); + // Add role to a fragment application. WHen doing this we need to stop adding the role to the + // application mapping. + RoleBasicInfo sharedRoleBasicInfo = addRole(SHARED_APP_ROLE_NAME, APPLICATION_AUD, SHARED_APP_ID, roleDAO); + List appIDs = roleDAO.getAssociatedApplicationIdsByRoleId(sharedRoleBasicInfo.getId(), + SAMPLE_TENANT_DOMAIN); + // The role should not be associated with any application. + assertTrue(appIDs.isEmpty()); + // Assert the thread local properties to check whether the IS_FRAGMENT_APP is removed. + assertFalse(IdentityUtil.threadLocalProperties.get().containsKey(IS_FRAGMENT_APP)); + } + @Test public void testAddRoles() throws Exception { @@ -315,6 +348,95 @@ public void testGetRoles() throws Exception { Assert.assertEquals(getRoleNamesList(roles), expectedRoles); } + @Test + public void testGetRolesWithRequiredAttributes() throws Exception { + + RoleDAOImpl roleDAO = spy(new RoleDAOImpl()); + mockCacheClearing(roleDAO); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getUserDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityUtil.when(IdentityUtil::getPrimaryDomainName).thenReturn(USER_DOMAIN_PRIMARY); + identityUtil.when(() -> IdentityUtil.extractDomainFromName(anyString())).thenCallRealMethod(); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(anyString())).thenReturn(SAMPLE_TENANT_ID); + + addRole(roleNamesList.get(0), APPLICATION_AUD, SAMPLE_APP_ID, roleDAO); + addRole(roleNamesList.get(1), APPLICATION_AUD, SAMPLE_APP_ID, roleDAO); + addRole(roleNamesList.get(2), ORGANIZATION_AUD, SAMPLE_ORG_ID, roleDAO); + + identityUtil.when(IdentityUtil::getDefaultItemsPerPage) + .thenReturn(IdentityCoreConstants.DEFAULT_ITEMS_PRE_PAGE); + identityUtil.when(IdentityUtil::getMaximumItemPerPage) + .thenReturn(IdentityCoreConstants.DEFAULT_MAXIMUM_ITEMS_PRE_PAGE); + + List requiredAttributes = new ArrayList<>(); + requiredAttributes.add(ROLE_PROPERTIES); + List roles = roleDAO.getRoles(10, 1, null, null, SAMPLE_TENANT_DOMAIN, requiredAttributes); + assertEquals(roles.size(), 3); + for (Role role : roles) { + assertNotNull(role.getRoleProperties()); + assertEquals(role.getRoleProperties().get(0).getName(), IS_SHARED_ROLE); + assertEquals(role.getRoleProperties().get(0).getValue(), Boolean.FALSE.toString()); + } + } + + @Test + public void testGetRoleById() throws Exception { + + RoleDAOImpl roleDAO = spy(new RoleDAOImpl()); + mockCacheClearing(roleDAO); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getUserDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityUtil.when(IdentityUtil::getPrimaryDomainName).thenReturn(USER_DOMAIN_PRIMARY); + identityUtil.when(() -> IdentityUtil.extractDomainFromName(anyString())).thenCallRealMethod(); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(anyString())).thenReturn(SAMPLE_TENANT_ID); + + RoleBasicInfo roleBasicInfo = addRole(roleNamesList.get(0), APPLICATION_AUD, SAMPLE_APP_ID, roleDAO); + + mockRealmConfiguration(); + Role role = roleDAO.getRole(roleBasicInfo.getId(), SAMPLE_TENANT_DOMAIN); + assertEquals(roleBasicInfo.getId(), role.getId()); + assertEquals(role.getRoleProperties().get(0).getName(), IS_SHARED_ROLE); + assertEquals(role.getRoleProperties().get(0).getValue(), Boolean.FALSE.toString()); + } + + @Test + public void testGetRoleByIdWithSharedRole() throws Exception { + + RoleDAOImpl roleDAO = spy(new RoleDAOImpl()); + mockCacheClearing(roleDAO); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getUserDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())) + .thenAnswer(invocation -> getConnection()); + identityUtil.when(IdentityUtil::getPrimaryDomainName).thenReturn(USER_DOMAIN_PRIMARY); + identityUtil.when(() -> IdentityUtil.extractDomainFromName(anyString())).thenCallRealMethod(); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(anyString())).thenReturn(SAMPLE_TENANT_ID); + userCoreUtil.when(() -> UserCoreUtil.isEveryoneRole(anyString(), any(RealmConfiguration.class))) + .thenReturn(false); + userCoreUtil.when(() -> UserCoreUtil.removeDomainFromName(anyString())).thenCallRealMethod(); + + // Constructing a shared role scenario + RoleBasicInfo roleBasicInfo = addRole(SHARED_ORG_ROLE_NAME, ORGANIZATION_AUD, SAMPLE_ORG_ID, roleDAO); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(L1_ORG_TENANT_DOMAIN)).thenReturn(2); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantDomain(2)).thenReturn(L1_ORG_TENANT_DOMAIN); + OrganizationManager organizationManager = mock(OrganizationManager.class); + lenient().when(organizationManager.resolveOrganizationId(anyString())).thenReturn(SAMPLE_ORG_ID); + RoleBasicInfo sharedRoleBasicInfo = addRole(SHARED_ORG_ROLE_NAME, ORGANIZATION_AUD, + L1_ORG_TENANT_ORG_ID, roleDAO); + roleDAO.addMainRoleToSharedRoleRelationship(roleBasicInfo.getId(), sharedRoleBasicInfo.getId(), + SAMPLE_TENANT_DOMAIN, L1_ORG_TENANT_DOMAIN); + + mockRealmConfiguration(); + Role role = roleDAO.getRole(sharedRoleBasicInfo.getId(), L1_ORG_TENANT_DOMAIN); + assertEquals(sharedRoleBasicInfo.getId(), role.getId()); + assertEquals(role.getRoleProperties().get(0).getName(), IS_SHARED_ROLE); + assertEquals(role.getRoleProperties().get(0).getValue(), Boolean.TRUE.toString()); + } + @Test public void testGetRolesWithFilter() throws Exception { diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/resources/testng.xml b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/resources/testng.xml index ec76ff550bdb..13e80e1d7fe7 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/resources/testng.xml +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/test/resources/testng.xml @@ -23,6 +23,7 @@ + diff --git a/components/role-mgt/pom.xml b/components/role-mgt/pom.xml index 82cf5d6dd32a..bce0fc010994 100644 --- a/components/role-mgt/pom.xml +++ b/components/role-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/pom.xml b/components/rule-mgt/org.wso2.carbon.identity.rule.management/pom.xml new file mode 100644 index 000000000000..eb0c64971890 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/pom.xml @@ -0,0 +1,219 @@ + + + + + + org.wso2.carbon.identity.framework + rule-mgt + 7.7.48-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.identity.rule.management + bundle + WSO2 Identity - Rule Management Component + Rule management backend component + http://wso2.org + + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.core + + + org.wso2.carbon.utils + org.wso2.carbon.database.utils + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.central.log.mgt + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.rule.metadata + + + com.fasterxml.jackson.core + jackson-databind + + + + org.testng + testng + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-testng + test + + + com.h2database + h2 + test + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.testutil + test + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + ${project.artifactId} + + ${project.artifactId} + + org.wso2.carbon.identity.rule.management.internal, + org.wso2.carbon.identity.rule.management.constant, + org.wso2.carbon.identity.rule.management.dao.*, + org.wso2.carbon.identity.rule.management.model.internal, + org.wso2.carbon.identity.rule.management.service.impl, + + + !org.wso2.carbon.identity.rule.management.internal, + !org.wso2.carbon.identity.rule.management.constant, + !org.wso2.carbon.identity.rule.management.dao.*, + !org.wso2.carbon.identity.rule.management.model.internal, + !org.wso2.carbon.identity.rule.management.service.impl, + org.wso2.carbon.identity.rule.management.*; + version="${carbon.identity.package.export.version}", + + + org.apache.commons.lang; version="${commons-lang.wso2.osgi.version.range}", + org.apache.commons.logging; version="${import.package.version.commons.logging}", + org.apache.commons.collections; version="${commons-collections.wso2.osgi.version.range}", + org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", + org.wso2.carbon.utils; version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.identity.central.log.mgt.utils; + version="${carbon.identity.package.import.version.range}", + com.fasterxml.jackson.core.*; version="${com.fasterxml.jackson.annotation.version.range}", + com.fasterxml.jackson.databind.*; + version="${com.fasterxml.jackson.annotation.version.range}", + com.fasterxml.jackson.annotation.*; + version="${com.fasterxml.jackson.annotation.version.range}", + org.wso2.carbon.database.utils.jdbc; + version="${org.wso2.carbon.database.utils.version.range}", + org.wso2.carbon.database.utils.jdbc.exceptions; + version="${org.wso2.carbon.database.utils.version.range}", + org.wso2.carbon.identity.core.cache; + version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.rule.metadata.*; + version="${carbon.identity.package.import.version.range}", + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.plugin.version} + + + src/test/resources/testng.xml + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + default-prepare-agent + + prepare-agent + + + + default-prepare-agent-integration + + prepare-agent-integration + + + + default-report + + report + + + + default-report-integration + + report-integration + + + + default-check + + check + + + + + BUNDLE + + + LINE + COVEREDRATIO + 0.80 + + + COMPLEXITY + COVEREDRATIO + 0.60 + + + + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + ../../../spotbugs-exclude.xml + Max + Low + true + true + + + + + diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCache.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCache.java new file mode 100644 index 000000000000..09c68b822f21 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCache.java @@ -0,0 +1,42 @@ +/* + * 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.rule.management.cache; + +import org.wso2.carbon.identity.core.cache.BaseCache; +import org.wso2.carbon.utils.CarbonUtils; + +/** + * Cache for Rule Management. + */ +public class RuleCache extends BaseCache { + + private static final String CACHE_NAME = "RuleCache"; + private static final RuleCache INSTANCE = new RuleCache(); + + public RuleCache() { + + super(CACHE_NAME); + } + + public static RuleCache getInstance() { + + CarbonUtils.checkSecurity(); + return INSTANCE; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCacheEntry.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCacheEntry.java new file mode 100644 index 000000000000..8080bf5c2934 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCacheEntry.java @@ -0,0 +1,48 @@ +/* + * 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.rule.management.cache; + +import org.wso2.carbon.identity.core.cache.CacheEntry; +import org.wso2.carbon.identity.rule.management.model.Rule; + +/** + * Cache entry for Rule Management. + * This class is used to store Rule object in cache. + */ +public class RuleCacheEntry extends CacheEntry { + + private static final long serialVersionUID = -8205516043545934797L; + + private Rule rule; + + public RuleCacheEntry(Rule rule) { + + this.rule = rule; + } + + public Rule getRule() { + + return rule; + } + + public void setRule(Rule rule) { + + this.rule = rule; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCacheKey.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCacheKey.java new file mode 100644 index 000000000000..2ace44abc42c --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/cache/RuleCacheKey.java @@ -0,0 +1,57 @@ +/* + * 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.rule.management.cache; + +import org.wso2.carbon.identity.core.cache.CacheKey; + +/** + * Cache key for Rule Management. + * This class is used to store Rule ID in cache. + */ +public class RuleCacheKey extends CacheKey { + + private static final long serialVersionUID = -6662958252110402724L; + + private final String ruleId; + + public RuleCacheKey(String ruleId) { + + this.ruleId = ruleId; + } + + public String getRuleId() { + + return ruleId; + } + + @Override + public boolean equals(Object o) { + + if (!(o instanceof RuleCacheKey)) { + return false; + } + return ruleId.equals(((RuleCacheKey) o).getRuleId()); + } + + @Override + public int hashCode() { + + return ruleId.hashCode(); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/constant/RuleSQLConstants.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/constant/RuleSQLConstants.java new file mode 100644 index 000000000000..7dca06852288 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/constant/RuleSQLConstants.java @@ -0,0 +1,77 @@ +/* + * 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.rule.management.constant; + +/** + * SQL Constants for Rule Management. + * This class is used to store SQL queries and column names. + */ +public class RuleSQLConstants { + + private RuleSQLConstants() { + + } + + /** + * This class is used to store column names. + */ + public static class Column { + + public static final String RULE_INTERNAL_ID = "ID"; + public static final String RULE_EXTERNAL_ID = "UUID"; + public static final String RULE_CONTENT = "CONTENT"; + public static final String IS_ACTIVE = "IS_ACTIVE"; + public static final String TENANT_ID = "TENANT_ID"; + public static final String VERSION = "VERSION"; + public static final String RULE_REFERENCE_ID = "RULE_ID"; + public static final String FIELD_NAME = "FIELD_NAME"; + public static final String FIELD_REFERENCE = "FIELD_REFERENCE"; + + private Column() { + + } + } + + /** + * This class is used to store SQL queries. + */ + public static class Query { + + public static final String ADD_RULE = "INSERT INTO IDN_RULE (UUID, CONTENT, IS_ACTIVE, TENANT_ID, VERSION) " + + "VALUES (:UUID;, :CONTENT;, :IS_ACTIVE;, :TENANT_ID;, :VERSION;)"; + public static final String ADD_RULE_REFERENCES = "INSERT INTO IDN_RULE_REFERENCES (RULE_ID, " + + "FIELD_NAME, FIELD_REFERENCE, TENANT_ID) VALUES (:RULE_ID;, :FIELD_NAME;, :FIELD_REFERENCE;, " + + ":TENANT_ID;)"; + public static final String UPDATE_RULE = + "UPDATE IDN_RULE SET CONTENT = :CONTENT; WHERE UUID = :UUID; AND TENANT_ID = :TENANT_ID;"; + public static final String DELETE_RULE_REFERENCES = + "DELETE FROM IDN_RULE_REFERENCES WHERE RULE_ID = :RULE_ID; AND TENANT_ID = :TENANT_ID;"; + public static final String DELETE_RULE = "DELETE FROM IDN_RULE WHERE UUID = :UUID; AND TENANT_ID = :TENANT_ID;"; + public static final String CHANGE_RULE_STATUS = "UPDATE IDN_RULE SET IS_ACTIVE = :IS_ACTIVE; WHERE UUID = " + + ":UUID; AND TENANT_ID = :TENANT_ID;"; + public static final String GET_RULE_BY_ID = + "SELECT CONTENT, IS_ACTIVE FROM IDN_RULE WHERE UUID = :UUID; AND TENANT_ID = :TENANT_ID;"; + public static final String GET_RULE_INTERNAL_ID_BY_ID = + "SELECT ID FROM IDN_RULE WHERE UUID = :UUID; AND TENANT_ID = :TENANT_ID;"; + + private Query() { + + } + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/RuleManagementDAO.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/RuleManagementDAO.java new file mode 100644 index 000000000000..ccb873e7504e --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/RuleManagementDAO.java @@ -0,0 +1,84 @@ +/* + * 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.rule.management.dao; + +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Rule; + +/** + * Rule Management DAO. + * This class is used to perform CRUD operations on Rule in the datastore. + */ +public interface RuleManagementDAO { + + /** + * Add a new Rule. + * + * @param rule Rule object + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + public void addRule(Rule rule, int tenantId) throws RuleManagementException; + + /** + * Update an existing Rule. + * + * @param rule Rule object + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + public void updateRule(Rule rule, int tenantId) throws RuleManagementException; + + /** + * Delete a Rule. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + public void deleteRule(String ruleId, int tenantId) throws RuleManagementException; + + /** + * Get a Rule by Rule ID. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @return Rule object + * @throws RuleManagementException Rule Management Exception + */ + public Rule getRuleByRuleId(String ruleId, int tenantId) throws RuleManagementException; + + /** + * Activate a Rule. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + public void activateRule(String ruleId, int tenantId) throws RuleManagementException; + + /** + * Deactivate a Rule. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + public void deactivateRule(String ruleId, int tenantId) throws RuleManagementException; +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/impl/CacheBackedRuleManagementDAO.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/impl/CacheBackedRuleManagementDAO.java new file mode 100644 index 000000000000..e926a34f2965 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/impl/CacheBackedRuleManagementDAO.java @@ -0,0 +1,152 @@ +/* + * 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.rule.management.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.rule.management.cache.RuleCache; +import org.wso2.carbon.identity.rule.management.cache.RuleCacheEntry; +import org.wso2.carbon.identity.rule.management.cache.RuleCacheKey; +import org.wso2.carbon.identity.rule.management.dao.RuleManagementDAO; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Rule; + +/** + * Cache backed Rule Management DAO. + * This class is used to implement the caching on top of the data layer operations. + * This caches the Rule object. + */ +public class CacheBackedRuleManagementDAO implements RuleManagementDAO { + + private static final Log LOG = LogFactory.getLog(CacheBackedRuleManagementDAO.class); + + private final RuleManagementDAO ruleManagementDAO; + private final RuleCache ruleCache; + + public CacheBackedRuleManagementDAO(RuleManagementDAO ruleManagementDAO) { + + this.ruleManagementDAO = ruleManagementDAO; + ruleCache = RuleCache.getInstance(); + } + + /** + * Add a new Rule. + * This method is used directly invokes the data layer operation to add the Rule. + * + * @param rule Rule object + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + @Override + public void addRule(Rule rule, int tenantId) throws RuleManagementException { + + ruleManagementDAO.addRule(rule, tenantId); + } + + /** + * Update an existing Rule. + * This method clears the cache entry upon rule update. + * + * @param rule Rule object + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + @Override + public void updateRule(Rule rule, int tenantId) throws RuleManagementException { + + ruleCache.clearCacheEntry(new RuleCacheKey(rule.getId()), tenantId); + LOG.debug("Rule cache entry is cleared for rule id: " + rule.getId() + " for rule update."); + ruleManagementDAO.updateRule(rule, tenantId); + } + + /** + * Delete a Rule. + * This method clears the cache entry upon rule deletion. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + @Override + public void deleteRule(String ruleId, int tenantId) throws RuleManagementException { + + ruleCache.clearCacheEntry(new RuleCacheKey(ruleId), tenantId); + LOG.debug("Rule cache entry is cleared for rule id: " + ruleId + " for rule deletion."); + ruleManagementDAO.deleteRule(ruleId, tenantId); + } + + /** + * Get a Rule by Rule ID. + * This method first checks the cache for the Rule object. + * If the Rule object is not found in the cache, it invokes the data layer operation to get the Rule. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @return Rule object + * @throws RuleManagementException Rule Management Exception + */ + @Override + public Rule getRuleByRuleId(String ruleId, int tenantId) throws RuleManagementException { + + RuleCacheEntry ruleCacheEntry = ruleCache.getValueFromCache(new RuleCacheKey(ruleId), tenantId); + if (ruleCacheEntry != null && ruleCacheEntry.getRule() != null) { + LOG.debug("Rule cache hit for rule id: " + ruleId + ". Returning from cache."); + return ruleCacheEntry.getRule(); + } + + Rule rule = ruleManagementDAO.getRuleByRuleId(ruleId, tenantId); + if (rule != null) { + LOG.debug("Rule cache miss for rule id: " + ruleId + ". Adding to cache."); + ruleCache.addToCache(new RuleCacheKey(ruleId), new RuleCacheEntry(rule), tenantId); + } + return rule; + } + + /** + * Activate a Rule. + * This method clears the cache entry upon rule activation. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + @Override + public void activateRule(String ruleId, int tenantId) throws RuleManagementException { + + ruleCache.clearCacheEntry(new RuleCacheKey(ruleId), tenantId); + LOG.debug("Rule cache entry is cleared for rule id: " + ruleId + " for rule activation."); + ruleManagementDAO.activateRule(ruleId, tenantId); + } + + /** + * Deactivate a Rule. + * This method clears the cache entry upon rule deactivation. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException Rule Management Exception + */ + @Override + public void deactivateRule(String ruleId, int tenantId) throws RuleManagementException { + + ruleCache.clearCacheEntry(new RuleCacheKey(ruleId), tenantId); + LOG.debug("Rule cache entry is cleared for rule id: " + ruleId + " for rule deactivation."); + ruleManagementDAO.deactivateRule(ruleId, tenantId); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/impl/RuleManagementDAOImpl.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/impl/RuleManagementDAOImpl.java new file mode 100644 index 000000000000..d87dab7cca1c --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/dao/impl/RuleManagementDAOImpl.java @@ -0,0 +1,326 @@ +/* + * 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.rule.management.dao.impl; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; +import org.wso2.carbon.identity.rule.management.constant.RuleSQLConstants; +import org.wso2.carbon.identity.rule.management.dao.RuleManagementDAO; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementServerException; +import org.wso2.carbon.identity.rule.management.model.Expression; +import org.wso2.carbon.identity.rule.management.model.Rule; +import org.wso2.carbon.identity.rule.management.model.Value; +import org.wso2.carbon.identity.rule.management.model.internal.ANDCombinedRule; +import org.wso2.carbon.identity.rule.management.model.internal.ORCombinedRule; +import org.wso2.carbon.identity.rule.management.model.internal.RuleData; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +/** + * Rule Management DAO Implementation. + * This class is used to perform CRUD operations on Rule in the database. + */ +public class RuleManagementDAOImpl implements RuleManagementDAO { + + private static final String V1 = "1.0.0"; + + /** + * This method will add the Rule to the database and add the Rule Value References to the database. + * + * @param rule Rule object + * @param tenantId Tenant ID + * @throws RuleManagementException If an error occurs while adding the rule to the database. + */ + @Override + public void addRule(Rule rule, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + int internalId = addRuleToDB(rule, tenantId); + addRuleValueReferencesToDB(internalId, rule, tenantId); + return null; + }); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while creating the rule in the system.", e); + } + } + + /** + * This method will update the Rule in the database and update the Rule Value References in the database, + * by deleting all and adding back reference values for the updated rule. + * + * @param rule Rule object + * @param tenantId Tenant ID + * @throws RuleManagementException If an error occurs while updating the rule in the database. + */ + @Override + public void updateRule(Rule rule, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + updateRuleInDB(rule, tenantId); + int internalRuleId = getInternalRuleIdByRuleId(rule.getId(), tenantId); + deleteRuleReferencesInDB(internalRuleId, tenantId); + addRuleValueReferencesToDB(internalRuleId, rule, tenantId); + return null; + }); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while updating the rule in the system.", e); + } + } + + /** + * This method will delete the Rule from the database. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException If an error occurs while deleting the rule from the database. + */ + @Override + public void deleteRule(String ruleId, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(RuleSQLConstants.Query.DELETE_RULE, + statement -> { + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, ruleId); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + }); + + return null; + }); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while deleting the rule in the system.", e); + } + } + + /** + * This method will retrieve the Rule from the database. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @return Rule object + * @throws RuleManagementException If an error occurs while retrieving the rule from the database. + */ + @Override + public Rule getRuleByRuleId(String ruleId, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + RuleData ruleData = new RuleData(); + try { + jdbcTemplate.withTransaction( + template -> template.fetchSingleRecord(RuleSQLConstants.Query.GET_RULE_BY_ID, + (resultSet, rowNumber) -> { + ruleData.setRuleJson(resultSet.getString(RuleSQLConstants.Column.RULE_CONTENT)); + ruleData.setActive(resultSet.getBoolean(RuleSQLConstants.Column.IS_ACTIVE)); + return null; + }, + statement -> { + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, ruleId); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + })); + + if (ruleData.getRuleJson() == null) { + return null; + } + + return new ORCombinedRule.Builder(convertJsonToRule(ruleData.getRuleJson())) + .setId(ruleId) + .setActive(ruleData.isActive()) + .build(); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while retrieving the rule from the system.", e); + } + } + + /** + * This method will activate the Rule in the database. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException If an error occurs while activating the rule in the database. + */ + @Override + public void activateRule(String ruleId, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(RuleSQLConstants.Query.CHANGE_RULE_STATUS, + statement -> { + statement.setBoolean(RuleSQLConstants.Column.IS_ACTIVE, true); + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, ruleId); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + }); + return null; + }); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while activating the rule in the system.", e); + } + } + + /** + * This method will deactivate the Rule in the database. + * + * @param ruleId Rule ID + * @param tenantId Tenant ID + * @throws RuleManagementException If an error occurs while deactivating the rule in the database. + */ + @Override + public void deactivateRule(String ruleId, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(RuleSQLConstants.Query.CHANGE_RULE_STATUS, + statement -> { + statement.setBoolean(RuleSQLConstants.Column.IS_ACTIVE, false); + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, ruleId); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + }); + return null; + }); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while deactivating the rule in the system.", e); + } + } + + private int addRuleToDB(Rule rule, int tenantId) + throws TransactionException, IOException, RuleManagementException { + + InputStream ruleJsonAsInputStream = convertRuleToJson(rule); + int ruleJsonStreamLength = ruleJsonAsInputStream.available(); + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + int internalRuleId = + jdbcTemplate.withTransaction(template -> template.executeInsert(RuleSQLConstants.Query.ADD_RULE, + statement -> { + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, rule.getId()); + statement.setBinaryStream(RuleSQLConstants.Column.RULE_CONTENT, ruleJsonAsInputStream, + ruleJsonStreamLength); + statement.setBoolean(RuleSQLConstants.Column.IS_ACTIVE, rule.isActive()); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + statement.setString(RuleSQLConstants.Column.VERSION, V1); + }, rule, true)); + // Not all JDBC drivers support getting the auto generated database ID. + // So if the ID is not returned, get the ID by querying the database. + if (internalRuleId == 0) { + internalRuleId = getInternalRuleIdByRuleId(rule.getId(), tenantId); + } + + return internalRuleId; + } + + private int getInternalRuleIdByRuleId(String ruleId, int tenantId) throws RuleManagementException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + try { + return jdbcTemplate.withTransaction( + template -> template.fetchSingleRecord(RuleSQLConstants.Query.GET_RULE_INTERNAL_ID_BY_ID, + (resultSet, rowNumber) -> resultSet.getInt(RuleSQLConstants.Column.RULE_INTERNAL_ID), + statement -> { + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, ruleId); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + })); + } catch (TransactionException e) { + throw new RuleManagementServerException("Error while retrieving the rule from the system.", e); + } + } + + private void addRuleValueReferencesToDB(int internalRuleId, Rule rule, int tenantId) throws TransactionException { + + ORCombinedRule orCombinedRule = (ORCombinedRule) rule; + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + jdbcTemplate.withTransaction(template -> template.executeBatchInsert(RuleSQLConstants.Query.ADD_RULE_REFERENCES, + statement -> { + for (ANDCombinedRule rule1 : orCombinedRule.getRules()) { + for (Expression expression : rule1.getExpressions()) { + if (expression.getValue().getType() == Value.Type.REFERENCE) { + statement.setInt(RuleSQLConstants.Column.RULE_REFERENCE_ID, internalRuleId); + statement.setString(RuleSQLConstants.Column.FIELD_NAME, expression.getField()); + statement.setString(RuleSQLConstants.Column.FIELD_REFERENCE, + expression.getValue().getFieldValue()); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + statement.addBatch(); + } + } + } + }, null)); + } + + private void updateRuleInDB(Rule rule, int tenantId) + throws IOException, TransactionException, RuleManagementServerException { + + InputStream ruleJsonAsInputStream = convertRuleToJson(rule); + int ruleJsonStreamLength = ruleJsonAsInputStream.available(); + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(RuleSQLConstants.Query.UPDATE_RULE, + statement -> { + statement.setBinaryStream(RuleSQLConstants.Column.RULE_CONTENT, ruleJsonAsInputStream, + ruleJsonStreamLength); + statement.setString(RuleSQLConstants.Column.RULE_EXTERNAL_ID, rule.getId()); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + }); + return null; + }); + } + + private void deleteRuleReferencesInDB(int internalRuleId, int tenantId) throws TransactionException { + + NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource()); + jdbcTemplate.withTransaction(template -> { + template.executeUpdate(RuleSQLConstants.Query.DELETE_RULE_REFERENCES, + statement -> { + statement.setInt(RuleSQLConstants.Column.RULE_REFERENCE_ID, internalRuleId); + statement.setInt(RuleSQLConstants.Column.TENANT_ID, tenantId); + }); + return null; + }); + } + + private InputStream convertRuleToJson(Rule rule) throws RuleManagementServerException { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + return new ByteArrayInputStream(objectMapper.writeValueAsString(rule).getBytes(StandardCharsets.UTF_8)); + } catch (JsonProcessingException e) { + throw new RuleManagementServerException("Failed to convert rule to JSON.", e); + } + } + + private ORCombinedRule convertJsonToRule(String ruleJson) throws RuleManagementServerException { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(ruleJson, ORCombinedRule.class); + } catch (JsonProcessingException e) { + throw new RuleManagementServerException("Failed to convert JSON to rule.", e); + } + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementClientException.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementClientException.java new file mode 100644 index 000000000000..2375fcef1fba --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementClientException.java @@ -0,0 +1,36 @@ +/* + * 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.rule.management.exception; + +/** + * Rule Management Client Exception. + * This class is used to handle client exceptions in Rule Management. + */ +public class RuleManagementClientException extends RuleManagementException { + + public RuleManagementClientException(String message) { + + super(message); + } + + public RuleManagementClientException(String message, Throwable cause) { + + super(message, cause); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementException.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementException.java new file mode 100644 index 000000000000..f821bf7db653 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementException.java @@ -0,0 +1,36 @@ +/* + * 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.rule.management.exception; + +/** + * Rule Management Exception. + * This class is used to handle exceptions in Rule Management. + */ +public class RuleManagementException extends Exception { + + public RuleManagementException(String message) { + + super(message); + } + + public RuleManagementException(String message, Throwable cause) { + + super(message, cause); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementServerException.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementServerException.java new file mode 100644 index 000000000000..fe214941bb6e --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/exception/RuleManagementServerException.java @@ -0,0 +1,36 @@ +/* + * 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.rule.management.exception; + +/** + * Rule Management Server Exception. + * This class is used to handle server exceptions in Rule Management. + */ +public class RuleManagementServerException extends RuleManagementException { + + public RuleManagementServerException(String message) { + + super(message); + } + + public RuleManagementServerException(String message, Throwable cause) { + + super(message, cause); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/internal/RuleManagementComponentServiceHolder.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/internal/RuleManagementComponentServiceHolder.java new file mode 100644 index 000000000000..f64827a3eeec --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/internal/RuleManagementComponentServiceHolder.java @@ -0,0 +1,50 @@ +/* + * 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.rule.management.internal; + +import org.wso2.carbon.identity.rule.metadata.service.RuleMetadataService; + +/** + * Rule Management Component Service Holder. + */ +public class RuleManagementComponentServiceHolder { + + private static final RuleManagementComponentServiceHolder INSTANCE = new RuleManagementComponentServiceHolder(); + + private RuleMetadataService ruleMetadataService; + + private RuleManagementComponentServiceHolder() { + + } + + public static RuleManagementComponentServiceHolder getInstance() { + + return INSTANCE; + } + + public RuleMetadataService getRuleMetadataService() { + + return ruleMetadataService; + } + + public void setRuleMetadataService(RuleMetadataService ruleMetadataService) { + + this.ruleMetadataService = ruleMetadataService; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/internal/RuleManagementServiceComponent.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/internal/RuleManagementServiceComponent.java new file mode 100644 index 000000000000..5d42ce9675de --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/internal/RuleManagementServiceComponent.java @@ -0,0 +1,96 @@ +/* + * 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.rule.management.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.wso2.carbon.identity.rule.management.service.RuleManagementService; +import org.wso2.carbon.identity.rule.management.service.impl.RuleManagementServiceImpl; +import org.wso2.carbon.identity.rule.metadata.service.RuleMetadataService; + +/** + * Rule Management Service Component. + */ +@Component( + name = "rule.management.service.component", + immediate = true +) +public class RuleManagementServiceComponent { + + private static final Log LOG = LogFactory.getLog(RuleManagementServiceComponent.class); + + @Activate + protected void activate(ComponentContext context) { + + try { + BundleContext bundleCtx = context.getBundleContext(); + + bundleCtx.registerService(RuleManagementService.class.getName(), + RuleManagementServiceImpl.getInstance(), null); + LOG.debug("Rule management bundle is activated."); + } catch (Throwable e) { + LOG.error("Error while initializing rule management service component.", e); + } + } + + @Deactivate + protected void deactivate(ComponentContext context) { + + try { + BundleContext bundleCtx = context.getBundleContext(); + bundleCtx.ungetService(bundleCtx.getServiceReference(RuleManagementService.class)); + LOG.debug("Rule management bundle is deactivated."); + } catch (Throwable e) { + LOG.error("Error while deactivating rule management service component.", e); + } + } + + @Reference( + name = "rule.metadata.service.component", + service = RuleMetadataService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetRuleMetadataService" + ) + protected void setRuleMetadataService(RuleMetadataService ruleMetadataService) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Registering a reference for RuleMetadataService in the rule management service component."); + } + + RuleManagementComponentServiceHolder.getInstance().setRuleMetadataService(ruleMetadataService); + } + + protected void unsetRuleMetadataService(RuleMetadataService ruleMetadataService) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Unregistering a reference for RuleMetadataService in the rule management service component."); + } + + RuleManagementComponentServiceHolder.getInstance().setRuleMetadataService(null); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Condition.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Condition.java new file mode 100644 index 000000000000..21b27ea43915 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Condition.java @@ -0,0 +1,26 @@ +/* + * 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.rule.management.model; + +/** + * This class is used to define the conditions in Rule Management. + */ +public enum Condition { + AND, OR +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Expression.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Expression.java new file mode 100644 index 000000000000..d68cd2372a5c --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Expression.java @@ -0,0 +1,90 @@ +/* + * 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.rule.management.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +/** + * Represents an expression in Rule Management. + * This class has a field, an operator and a value. + */ +@JsonDeserialize(builder = Expression.Builder.class) +public class Expression { + + private final String field; + private final String operator; + private final Value value; + + private Expression(Builder builder) { + + this.field = builder.field; + this.operator = builder.operator; + this.value = builder.value; + } + + public String getField() { + + return field; + } + + public String getOperator() { + + return operator; + } + + public Value getValue() { + + return value; + } + + /** + * Builder for the Expression. + */ + @JsonPOJOBuilder(withPrefix = "") + public static class Builder { + + private String field; + private String operator; + private Value value; + + public Builder field(String field) { + + this.field = field; + return this; + } + + public Builder operator(String operator) { + + this.operator = operator; + return this; + } + + public Builder value(Value value) { + + this.value = value; + return this; + } + + public Expression build() { + + return new Expression(this); + } + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/FlowType.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/FlowType.java new file mode 100644 index 000000000000..5f8d469f8b8e --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/FlowType.java @@ -0,0 +1,27 @@ +/* + * 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.rule.management.model; + +/** + * This class is used to define the flow types in Rule Management. + */ +public enum FlowType { + + PRE_ISSUE_ACCESS_TOKEN; +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Rule.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Rule.java new file mode 100644 index 000000000000..b752a68834b9 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Rule.java @@ -0,0 +1,52 @@ +/* + * 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.rule.management.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Represents a rule in Rule Management. + * This class has an id, a condition and a status. + */ +public abstract class Rule { + + protected String id; + protected Condition condition; + protected boolean isActive; + + /** + * @JsonIgnore annotation is used to ignore the id field when serializing and deserializing the object, + * to and from JSON in order to store in the database. + */ + @JsonIgnore + public String getId() { + + return id; + } + + /** + * @JsonIgnore annotation is used to ignore the active field when serializing and deserializing the object, + * to and from JSON in order to store in the database. + */ + @JsonIgnore + public boolean isActive() { + + return isActive; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Value.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Value.java new file mode 100644 index 000000000000..0549ee2bcc60 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/Value.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.rule.management.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a value in Rule Management. + * This class has a type and a value. + */ +public class Value { + + private final Type type; + private final String fieldValue; + + @JsonCreator + public Value(@JsonProperty("type") Type type, @JsonProperty("value") String fieldValue) { + + this.type = type; + this.fieldValue = fieldValue; + } + + public Type getType() { + return type; + } + + public String getFieldValue() { + return fieldValue; + } + + /** + * Represents the type of the value. + */ + public enum Type { + STRING, NUMBER, BOOLEAN, DATE_TIME, REFERENCE + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/ANDCombinedRule.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/ANDCombinedRule.java new file mode 100644 index 000000000000..9bdc57381cfb --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/ANDCombinedRule.java @@ -0,0 +1,94 @@ +/* + * 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.rule.management.model.internal; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import org.wso2.carbon.identity.rule.management.model.Condition; +import org.wso2.carbon.identity.rule.management.model.Expression; +import org.wso2.carbon.identity.rule.management.model.Rule; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Represents an AND combined rule. + * This class extends the Rule class and has a list of expressions. + */ +@JsonDeserialize(builder = ANDCombinedRule.Builder.class) +public class ANDCombinedRule extends Rule { + + private final List expressions; + + private ANDCombinedRule(Builder builder) { + + this.id = builder.id; + this.expressions = builder.expressions; + this.condition = Condition.AND; + this.isActive = true; + } + + public Condition getCondition() { + + return condition; + } + + public List getExpressions() { + + return expressions; + } + + /** + * Builder for the ANDCombinedRule. + */ + @JsonPOJOBuilder(withPrefix = "set") + public static class Builder { + + private String id; + private List expressions = new ArrayList<>(); + + public Builder addExpression(Expression expression) { + + expressions.add(expression); + return this; + } + + public Builder setCondition(Condition condition) { + + if (condition != Condition.AND) { + throw new IllegalArgumentException("Condition must be AND for ANDCombinedRule"); + } + + return this; + } + + public Builder setExpressions(List expressions) { + + this.expressions = expressions; + return this; + } + + public ANDCombinedRule build() { + + this.id = UUID.randomUUID().toString(); + return new ANDCombinedRule(this); + } + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/ORCombinedRule.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/ORCombinedRule.java new file mode 100644 index 000000000000..85124b6a5606 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/ORCombinedRule.java @@ -0,0 +1,119 @@ +/* + * 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.rule.management.model.internal; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import org.wso2.carbon.identity.rule.management.model.Condition; +import org.wso2.carbon.identity.rule.management.model.Rule; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Represents an OR combined rule. + * This class extends the Rule class and has a list of ANDCombinedRules. + */ +@JsonDeserialize(builder = ORCombinedRule.Builder.class) +public class ORCombinedRule extends Rule { + + private List rules; + + /** + * Builder for the ORCombinedRule. + */ + private ORCombinedRule(Builder builder) { + + this.id = builder.id; + this.isActive = builder.isActive; + this.rules = builder.rules; + this.condition = Condition.OR; + } + + public Condition getCondition() { + + return condition; + } + + public List getRules() { + + return rules; + } + + /** + * Builder for the ORCombinedRule. + */ + @JsonPOJOBuilder(withPrefix = "set") + public static class Builder { + + private String id; + private boolean isActive = true; + private List rules = new ArrayList<>(); + + public Builder() { + + } + + public Builder(ORCombinedRule orCombinedRule) { + + this.id = orCombinedRule.id; + this.rules = orCombinedRule.rules; + } + + public Builder addRule(ANDCombinedRule andCombinedRule) { + + rules.add(andCombinedRule); + return this; + } + + public Builder setId(String id) { + + this.id = id; + return this; + } + + public Builder setActive(boolean isActive) { + + this.isActive = isActive; + return this; + } + + public Builder setCondition(Condition condition) { + + if (condition != Condition.OR) { + throw new IllegalArgumentException("Condition must be OR for ORCombinedRule"); + } + + return this; + } + + public Builder setRules(List rules) { + + this.rules = rules; + return this; + } + + public ORCombinedRule build() { + + this.id = (this.id == null) ? UUID.randomUUID().toString() : this.id; + return new ORCombinedRule(this); + } + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/RuleData.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/RuleData.java new file mode 100644 index 000000000000..f3e592259c72 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/model/internal/RuleData.java @@ -0,0 +1,49 @@ +/* + * 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.rule.management.model.internal; + +/** + * Represents a rule in the data layer. + * This class has the rule JSON and the active status of the rule which is stored in the database. + */ +public class RuleData { + + private String ruleJson; + private boolean isActive; + + public String getRuleJson() { + + return ruleJson; + } + + public void setRuleJson(String ruleJson) { + + this.ruleJson = ruleJson; + } + + public boolean isActive() { + + return isActive; + } + + public void setActive(boolean active) { + + isActive = active; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/service/RuleManagementService.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/service/RuleManagementService.java new file mode 100644 index 000000000000..57f1b9678bdf --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/service/RuleManagementService.java @@ -0,0 +1,78 @@ +/* + * 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.rule.management.service; + +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Rule; + +/** + * This interface is used to define the Rule Management Service. + * This interface has the methods to add, update, delete, get and deactivate rules. + */ +public interface RuleManagementService { + + /** + * Adds a new rule. + * + * @param rule Rule to be added. + * @param tenantDomain Tenant domain. + * @return Added rule. + * @throws RuleManagementException If an error occurs while adding the rule. + */ + public Rule addRule(Rule rule, String tenantDomain) throws RuleManagementException; + + /** + * Updates an existing rule. + * + * @param rule Rule to be updated. + * @param tenantDomain Tenant domain. + * @return Updated rule. + * @throws RuleManagementException If an error occurs while updating the rule. + */ + public Rule updateRule(Rule rule, String tenantDomain) throws RuleManagementException; + + /** + * Deletes a rule. + * + * @param ruleId Rule ID. + * @param tenantDomain Tenant domain. + * @throws RuleManagementException If an error occurs while deleting the rule. + */ + public void deleteRule(String ruleId, String tenantDomain) throws RuleManagementException; + + /** + * Retrieves a rule by rule ID. + * + * @param ruleId Rule ID. + * @param tenantDomain Tenant domain. + * @return Rule. + * @throws RuleManagementException If an error occurs while retrieving the rule. + */ + public Rule getRuleByRuleId(String ruleId, String tenantDomain) throws RuleManagementException; + + /** + * Deactivates a rule. + * + * @param ruleId Rule ID. + * @param tenantDomain Tenant domain. + * @return Deactivated rule. + * @throws RuleManagementException If an error occurs while deactivating the rule. + */ + public Rule deactivateRule(String ruleId, String tenantDomain) throws RuleManagementException; +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/service/impl/RuleManagementServiceImpl.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/service/impl/RuleManagementServiceImpl.java new file mode 100644 index 000000000000..f60a40d38356 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/service/impl/RuleManagementServiceImpl.java @@ -0,0 +1,140 @@ +/* + * 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.rule.management.service.impl; + +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.rule.management.dao.RuleManagementDAO; +import org.wso2.carbon.identity.rule.management.dao.impl.CacheBackedRuleManagementDAO; +import org.wso2.carbon.identity.rule.management.dao.impl.RuleManagementDAOImpl; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementClientException; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Rule; +import org.wso2.carbon.identity.rule.management.service.RuleManagementService; + +/** + * Implementation of Rule Management Service. + */ +public class RuleManagementServiceImpl implements RuleManagementService { + + private static final RuleManagementServiceImpl ruleManagementService = new RuleManagementServiceImpl(); + private final RuleManagementDAO ruleManagementDAO; + + private RuleManagementServiceImpl() { + + ruleManagementDAO = new CacheBackedRuleManagementDAO(new RuleManagementDAOImpl()); + } + + public static RuleManagementServiceImpl getInstance() { + + return ruleManagementService; + } + + /** + * Add a new rule. + * + * @param rule Rule to be added. + * @param tenantDomain Tenant domain. + * @return Added rule. + * @throws RuleManagementException If an error occurs while adding the rule. + */ + @Override + public Rule addRule(Rule rule, String tenantDomain) throws RuleManagementException { + + int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); + ruleManagementDAO.addRule(rule, tenantId); + return ruleManagementDAO.getRuleByRuleId(rule.getId(), tenantId); + } + + /** + * Update an existing rule. + * + * @param rule Rule to be updated. + * @param tenantDomain Tenant domain. + * @return Updated rule. + * @throws RuleManagementException If an error occurs while updating the rule. + */ + @Override + public Rule updateRule(Rule rule, String tenantDomain) throws RuleManagementException { + + validateIfRuleExists(rule.getId(), tenantDomain); + + ruleManagementDAO.updateRule(rule, IdentityTenantUtil.getTenantId(tenantDomain)); + return ruleManagementDAO.getRuleByRuleId(rule.getId(), IdentityTenantUtil.getTenantId(tenantDomain)); + } + + /** + * Delete a rule. + * + * @param ruleId Rule ID. + * @param tenantDomain Tenant domain. + * @throws RuleManagementException If an error occurs while deleting the rule. + */ + @Override + public void deleteRule(String ruleId, String tenantDomain) throws RuleManagementException { + + if (isRuleExists(ruleId, tenantDomain)) { + ruleManagementDAO.deleteRule(ruleId, IdentityTenantUtil.getTenantId(tenantDomain)); + } + } + + /** + * Retrieve a rule by rule ID. + * + * @param ruleId Rule ID. + * @param tenantDomain Tenant domain. + * @return Rule. + * @throws RuleManagementException If an error occurs while retrieving the rule. + */ + @Override + public Rule getRuleByRuleId(String ruleId, String tenantDomain) throws RuleManagementException { + + return ruleManagementDAO.getRuleByRuleId(ruleId, IdentityTenantUtil.getTenantId(tenantDomain)); + } + + /** + * Deactivate a rule. + * + * @param ruleId Rule ID. + * @param tenantDomain Tenant domain. + * @return Deactivated rule. + * @throws RuleManagementException If an error occurs while deactivating the rule. + */ + @Override + public Rule deactivateRule(String ruleId, String tenantDomain) throws RuleManagementException { + + validateIfRuleExists(ruleId, tenantDomain); + + ruleManagementDAO.deactivateRule(ruleId, IdentityTenantUtil.getTenantId(tenantDomain)); + return ruleManagementDAO.getRuleByRuleId(ruleId, IdentityTenantUtil.getTenantId(tenantDomain)); + } + + private void validateIfRuleExists(String ruleId, String tenantDomain) throws RuleManagementException { + + if (!isRuleExists(ruleId, tenantDomain)) { + throw new RuleManagementClientException("Rule not found for the given rule id: " + ruleId); + } + } + + private boolean isRuleExists(String ruleId, String tenantDomain) throws RuleManagementException { + + Rule existingRule = + ruleManagementDAO.getRuleByRuleId(ruleId, IdentityTenantUtil.getTenantId(tenantDomain)); + return existingRule != null; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/util/RuleBuilder.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/util/RuleBuilder.java new file mode 100644 index 000000000000..e970988d53cd --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/util/RuleBuilder.java @@ -0,0 +1,219 @@ +/* + * 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.rule.management.util; + +import org.wso2.carbon.identity.rule.management.exception.RuleManagementClientException; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementServerException; +import org.wso2.carbon.identity.rule.management.internal.RuleManagementComponentServiceHolder; +import org.wso2.carbon.identity.rule.management.model.Expression; +import org.wso2.carbon.identity.rule.management.model.FlowType; +import org.wso2.carbon.identity.rule.management.model.Rule; +import org.wso2.carbon.identity.rule.management.model.internal.ANDCombinedRule; +import org.wso2.carbon.identity.rule.management.model.internal.ORCombinedRule; +import org.wso2.carbon.identity.rule.metadata.exception.RuleMetadataException; +import org.wso2.carbon.identity.rule.metadata.model.FieldDefinition; +import org.wso2.carbon.identity.rule.metadata.model.OptionsInputValue; + +import java.util.List; +import java.util.Map; + +/** + * RuleBuilder class is used to build a rule. + * The RuleBuilder instance can be created using the create method for a given flow type and tenant domain. + * This class provides methods to add expressions and conditions to the rule and to build the rule. + * Validations are done while adding expressions and conditions to the rule. + */ +public class RuleBuilder { + + private static final int MAX_EXPRESSIONS_COMBINED_WITH_AND = 5; + private static final int MAX_RULES_COMBINED_WITH_OR = 10; + + private final ORCombinedRule.Builder orCombinedRuleBuilder = new ORCombinedRule.Builder(); + private ANDCombinedRule.Builder andCombinedRuleBuilder = new ANDCombinedRule.Builder(); + private final Map expressionMetadataFieldsMap; + + private boolean isError = false; + private String errorMessage; + + private int andRuleCount = 0; + private int orRuleCount = 0; + + private RuleBuilder(List expressionMetadataFields) { + + this.expressionMetadataFieldsMap = expressionMetadataFields.stream() + .collect(java.util.stream.Collectors.toMap(fieldDefinition -> fieldDefinition.getField().getName(), + fieldDefinition -> fieldDefinition)); + } + + /** + * Add an expression to the rule. + * + * @param expression Expression to be added. + * @return RuleBuilder + */ + public RuleBuilder addAndExpression(Expression expression) { + + validateExpression(expression); + addExpressionForANDCombinedRule(expression); + validateMaxAllowedANDCombinedExpressions(); + return this; + } + + /** + * Add an OR condition to the rule. + * + * @return RuleBuilder + */ + public RuleBuilder addOrCondition() { + + addORCombinedRule(); + validateMaxAllowedORCombinedRules(); + initANDCombinedRule(); + return this; + } + + /** + * Build the rule. + * + * @return Rule + * @throws RuleManagementClientException If an error occurs while building the rule. + */ + public Rule build() throws RuleManagementClientException { + + if (isError) { + // The very first validation error will be thrown as an exception. + throw new RuleManagementClientException( + "Building rule failed due to validation errors. Error: " + errorMessage); + } + + orCombinedRuleBuilder.addRule(andCombinedRuleBuilder.build()); + return orCombinedRuleBuilder.build(); + } + + /** + * Create a RuleBuilder instance. + * + * @param flowType Flow type. + * @param tenantDomain Tenant domain. + * @return RuleBuilder + * @throws RuleManagementException If an error occurs while creating the RuleBuilder instance. + */ + public static RuleBuilder create(FlowType flowType, String tenantDomain) throws RuleManagementException { + + try { + List fieldDefinitionList = + RuleManagementComponentServiceHolder.getInstance().getRuleMetadataService() + .getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.valueOf(flowType.name()), + tenantDomain); + + if (fieldDefinitionList == null || fieldDefinitionList.isEmpty()) { + throw new RuleManagementClientException( + "Expression metadata from RuleMetadataService is null or empty."); + } + + return new RuleBuilder(fieldDefinitionList); + } catch (RuleMetadataException e) { + throw new RuleManagementServerException( + "Error while retrieving expression metadata from RuleMetadataService.", e); + } + } + + private void addExpressionForANDCombinedRule(Expression expression) { + + andCombinedRuleBuilder.addExpression(expression); + andRuleCount++; + } + + private void initANDCombinedRule() { + + andCombinedRuleBuilder = new ANDCombinedRule.Builder(); + andRuleCount = 0; + } + + private void addORCombinedRule() { + + orCombinedRuleBuilder.addRule(andCombinedRuleBuilder.build()); + orRuleCount++; + } + + private void validateExpression(Expression expression) { + + FieldDefinition fieldDefinition = expressionMetadataFieldsMap.get(expression.getField()); + + if (isError) { + return; + } + + if (fieldDefinition == null) { + setValidationError("Field " + expression.getField() + " is not supported"); + return; + } + + if (fieldDefinition.getOperators().stream() + .noneMatch(operator -> operator.getName().equals(expression.getOperator()))) { + setValidationError("Operator " + expression.getOperator() + " is not supported for field " + + expression.getField()); + return; + } + + if (!fieldDefinition.getValue().getValueType().name().equals(expression.getValue().getType().name())) { + setValidationError("Value type " + expression.getValue().getType().name() + " is not supported for field " + + expression.getField()); + } + + if (fieldDefinition.getValue() instanceof OptionsInputValue && + ((OptionsInputValue) fieldDefinition.getValue()).getValues().stream().noneMatch( + optionsValue -> optionsValue.getName().equals(expression.getValue().getFieldValue()))) { + setValidationError("Value " + expression.getValue().getFieldValue() + " is not supported for field " + + expression.getField()); + } + } + + private void validateMaxAllowedANDCombinedExpressions() { + + if (isError) { + return; + } + + if (andRuleCount > MAX_EXPRESSIONS_COMBINED_WITH_AND) { + setValidationError("Maximum number of expressions combined with AND exceeded. Maximum allowed: " + + MAX_EXPRESSIONS_COMBINED_WITH_AND + " Provided: " + andRuleCount); + } + } + + private void validateMaxAllowedORCombinedRules() { + + if (isError) { + return; + } + + if (orRuleCount > MAX_RULES_COMBINED_WITH_OR) { + setValidationError("Maximum number of rules combined with OR exceeded. Maximum allowed: " + + MAX_RULES_COMBINED_WITH_OR + " Provided: " + orRuleCount); + } + } + + private void setValidationError(String message) { + + isError = true; + errorMessage = message; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/dao/CacheBackedRuleManagementDAOTest.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/dao/CacheBackedRuleManagementDAOTest.java new file mode 100644 index 000000000000..fbe7f6661041 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/dao/CacheBackedRuleManagementDAOTest.java @@ -0,0 +1,199 @@ +/* + * 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.rule.management.dao; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.common.testng.WithRealmService; +import org.wso2.carbon.identity.core.internal.IdentityCoreServiceDataHolder; +import org.wso2.carbon.identity.rule.management.cache.RuleCache; +import org.wso2.carbon.identity.rule.management.cache.RuleCacheEntry; +import org.wso2.carbon.identity.rule.management.cache.RuleCacheKey; +import org.wso2.carbon.identity.rule.management.dao.impl.CacheBackedRuleManagementDAO; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Rule; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +@WithCarbonHome +@WithRealmService(injectToSingletons = {IdentityCoreServiceDataHolder.class}) +public class CacheBackedRuleManagementDAOTest { + + private RuleManagementDAO ruleManagementDAO; + private CacheBackedRuleManagementDAO cacheBackedRuleManagementDAO; + private RuleCache ruleCache; + + public static final String RULE_ID = "ruleId"; + public static final int TENANT_ID = 1; + + @BeforeClass + public void setUpClass() { + + ruleCache = RuleCache.getInstance(); + } + + @BeforeMethod + public void setUp() { + + ruleManagementDAO = mock(RuleManagementDAO.class); + cacheBackedRuleManagementDAO = new CacheBackedRuleManagementDAO(ruleManagementDAO); + } + + @Test + public void testAddRule() throws RuleManagementException { + + Rule rule = mock(Rule.class); + + cacheBackedRuleManagementDAO.addRule(rule, TENANT_ID); + + verify(ruleManagementDAO).addRule(rule, TENANT_ID); + } + + @Test + public void testUpdateRule() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + + cacheBackedRuleManagementDAO.updateRule(rule, TENANT_ID); + + verify(ruleManagementDAO).updateRule(rule, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testUpdateRuleWhenCacheIsPopulated() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + RuleCacheEntry cacheEntry = new RuleCacheEntry(rule); + ruleCache.addToCache(new RuleCacheKey(RULE_ID), cacheEntry, TENANT_ID); + + cacheBackedRuleManagementDAO.updateRule(rule, TENANT_ID); + + verify(ruleManagementDAO).updateRule(rule, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testDeleteRule() throws RuleManagementException { + + cacheBackedRuleManagementDAO.deleteRule(RULE_ID, TENANT_ID); + + verify(ruleManagementDAO).deleteRule(RULE_ID, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testDeleteRuleWhenCacheIsPopulated() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + RuleCacheEntry cacheEntry = new RuleCacheEntry(rule); + ruleCache.addToCache(new RuleCacheKey(RULE_ID), cacheEntry, TENANT_ID); + + cacheBackedRuleManagementDAO.deleteRule(RULE_ID, TENANT_ID); + + verify(ruleManagementDAO).deleteRule(RULE_ID, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testGetRuleByRuleIdCacheHit() throws RuleManagementException { + + Rule rule = mock(Rule.class); + RuleCacheEntry cacheEntry = new RuleCacheEntry(rule); + ruleCache.addToCache(new RuleCacheKey(RULE_ID), cacheEntry, TENANT_ID); + + Rule result = cacheBackedRuleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID); + + assertEquals(result, rule); + verify(ruleManagementDAO, never()).getRuleByRuleId(RULE_ID, TENANT_ID); + } + + @Test + public void testGetRuleByRuleIdCacheMiss() throws RuleManagementException { + + ruleCache.clear(TENANT_ID); + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(rule); + + Rule result = cacheBackedRuleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID); + + assertEquals(result, rule); + verify(ruleManagementDAO).getRuleByRuleId(RULE_ID, TENANT_ID); + // Verify that the rule is added to the cache + assertEquals(rule, ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID).getRule()); + } + + @Test + public void testActivateRule() throws RuleManagementException { + + cacheBackedRuleManagementDAO.activateRule(RULE_ID, TENANT_ID); + + verify(ruleManagementDAO).activateRule(RULE_ID, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testActivateRuleWhenCacheIsPopulated() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + RuleCacheEntry cacheEntry = new RuleCacheEntry(rule); + ruleCache.addToCache(new RuleCacheKey(RULE_ID), cacheEntry, TENANT_ID); + + cacheBackedRuleManagementDAO.activateRule(RULE_ID, TENANT_ID); + + verify(ruleManagementDAO).activateRule(RULE_ID, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testDeactivateRule() throws RuleManagementException { + + cacheBackedRuleManagementDAO.deactivateRule(RULE_ID, TENANT_ID); + + verify(ruleManagementDAO).deactivateRule(RULE_ID, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } + + @Test + public void testDeactivateRuleWhenCacheIsPopulated() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + RuleCacheEntry cacheEntry = new RuleCacheEntry(rule); + ruleCache.addToCache(new RuleCacheKey(RULE_ID), cacheEntry, TENANT_ID); + + cacheBackedRuleManagementDAO.deactivateRule(RULE_ID, TENANT_ID); + + verify(ruleManagementDAO).deactivateRule(RULE_ID, TENANT_ID); + assertNull(ruleCache.getValueFromCache(new RuleCacheKey(RULE_ID), TENANT_ID)); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/dao/RuleManagementDAOImplTest.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/dao/RuleManagementDAOImplTest.java new file mode 100644 index 000000000000..63a54980ec53 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/dao/RuleManagementDAOImplTest.java @@ -0,0 +1,228 @@ +/* + * 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.rule.management.dao; + +import org.testng.annotations.Test; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.common.testng.WithH2Database; +import org.wso2.carbon.identity.rule.management.dao.impl.RuleManagementDAOImpl; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Expression; +import org.wso2.carbon.identity.rule.management.model.Rule; +import org.wso2.carbon.identity.rule.management.model.Value; +import org.wso2.carbon.identity.rule.management.model.internal.ANDCombinedRule; +import org.wso2.carbon.identity.rule.management.model.internal.ORCombinedRule; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +@WithH2Database(files = {"dbscripts/h2.sql"}) +@WithCarbonHome +public class RuleManagementDAOImplTest { + + public static final int TENANT_ID = 1; + private Rule createdRule; + RuleManagementDAOImpl ruleManagementDAOImpl = new RuleManagementDAOImpl(); + + @Test + public void testAddRule() throws RuleManagementException { + + Expression expression1 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "authorization_code")).build(); + ANDCombinedRule andCombinedRule1 = + new ANDCombinedRule.Builder().addExpression(expression1).addExpression(expression2).build(); + + Expression expression3 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp2")).build(); + ANDCombinedRule andCombinedRule2 = + new ANDCombinedRule.Builder().addExpression(expression3).build(); + + ORCombinedRule orCombinedRule = + new ORCombinedRule.Builder().addRule(andCombinedRule1).addRule(andCombinedRule2).build(); + + ruleManagementDAOImpl.addRule(orCombinedRule, TENANT_ID); + + createdRule = ruleManagementDAOImpl.getRuleByRuleId(orCombinedRule.getId(), TENANT_ID); + assertNotNull(createdRule); + assertEquals(orCombinedRule.getId(), createdRule.getId()); + assertTrue(createdRule.isActive()); + + ORCombinedRule retrievedORCombinedRule = assertOrCombinedRule(createdRule, 2); + ANDCombinedRule retrievedAndCombinedRule1 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(0), 2); + assertExpressions(retrievedAndCombinedRule1, expression1, expression2); + ANDCombinedRule retrievedAndCombinedRule2 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(1), 1); + assertExpressions(retrievedAndCombinedRule2, expression3); + } + + @Test(dependsOnMethods = {"testAddRule"}) + public void testAddRuleWithMultipleExpressionsUsingSameFieldReferenceAndOR() throws RuleManagementException { + + Expression expression1 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "authorization_code")).build(); + + ANDCombinedRule andCombinedRule1 = + new ANDCombinedRule.Builder().addExpression(expression1).addExpression(expression2).build(); + + Expression expression3 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + + Expression expression4 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "client_credentials")).build(); + + ANDCombinedRule andCombinedRule2 = + new ANDCombinedRule.Builder().addExpression(expression3).addExpression(expression4).build(); + + Expression expression5 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp2")).build(); + ANDCombinedRule andCombinedRule3 = + new ANDCombinedRule.Builder().addExpression(expression5).build(); + + ORCombinedRule orCombinedRule = + new ORCombinedRule.Builder().addRule(andCombinedRule1).addRule(andCombinedRule2) + .addRule(andCombinedRule3).build(); + + ruleManagementDAOImpl.addRule(orCombinedRule, TENANT_ID); + + createdRule = ruleManagementDAOImpl.getRuleByRuleId(orCombinedRule.getId(), TENANT_ID); + assertNotNull(createdRule); + assertEquals(orCombinedRule.getId(), createdRule.getId()); + assertTrue(createdRule.isActive()); + + ORCombinedRule retrievedORCombinedRule = assertOrCombinedRule(createdRule, 3); + ANDCombinedRule retrievedAndCombinedRule1 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(0), 2); + assertExpressions(retrievedAndCombinedRule1, expression1, expression2); + ANDCombinedRule retrievedAndCombinedRule2 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(1), 2); + assertExpressions(retrievedAndCombinedRule2, expression3, expression4); + ANDCombinedRule retrievedAndCombinedRule3 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(2), 1); + assertExpressions(retrievedAndCombinedRule3, expression5); + } + + @Test(dependsOnMethods = {"testAddRuleWithMultipleExpressionsUsingSameFieldReferenceAndOR"}) + public void testUpdateRule() throws RuleManagementException { + + Expression expression1 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "password")).build(); + ANDCombinedRule andCombinedRule1 = + new ANDCombinedRule.Builder().addExpression(expression1).addExpression(expression2).build(); + + Expression expression3 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp2")).build(); + ANDCombinedRule andCombinedRule2 = + new ANDCombinedRule.Builder().addExpression(expression3).build(); + + Expression expression4 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp4")).build(); + ANDCombinedRule andCombinedRule3 = + new ANDCombinedRule.Builder().addExpression(expression4).build(); + + ORCombinedRule orCombinedRule = + new ORCombinedRule.Builder().setId(createdRule.getId()).addRule(andCombinedRule1) + .addRule(andCombinedRule2) + .addRule(andCombinedRule3).build(); + + ruleManagementDAOImpl.updateRule(orCombinedRule, TENANT_ID); + + Rule updatedRule = ruleManagementDAOImpl.getRuleByRuleId(createdRule.getId(), TENANT_ID); + assertNotNull(updatedRule); + assertEquals(createdRule.getId(), updatedRule.getId()); + assertTrue(updatedRule.isActive()); + + ORCombinedRule retrievedORCombinedRule = assertOrCombinedRule(updatedRule, 3); + ANDCombinedRule retrievedAndCombinedRule1 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(0), 2); + assertExpressions(retrievedAndCombinedRule1, expression1, expression2); + ANDCombinedRule retrievedAndCombinedRule2 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(1), 1); + assertExpressions(retrievedAndCombinedRule2, expression3); + ANDCombinedRule retrievedAndCombinedRule3 = assertAndCombinedRule(retrievedORCombinedRule.getRules().get(2), 1); + assertExpressions(retrievedAndCombinedRule3, expression4); + } + + @Test(dependsOnMethods = {"testUpdateRule"}) + public void testDeactivateRule() throws RuleManagementException { + + ruleManagementDAOImpl.deactivateRule(createdRule.getId(), TENANT_ID); + Rule deactivatedRule = ruleManagementDAOImpl.getRuleByRuleId(createdRule.getId(), TENANT_ID); + assertNotNull(deactivatedRule); + assertEquals(deactivatedRule.getId(), createdRule.getId()); + assertFalse(deactivatedRule.isActive()); + } + + @Test(dependsOnMethods = {"testDeactivateRule"}) + public void testActivateRule() throws RuleManagementException { + + ruleManagementDAOImpl.activateRule(createdRule.getId(), TENANT_ID); + Rule activatedRule = ruleManagementDAOImpl.getRuleByRuleId(createdRule.getId(), TENANT_ID); + assertNotNull(activatedRule); + assertEquals(activatedRule.getId(), createdRule.getId()); + assertTrue(activatedRule.isActive()); + } + + @Test(dependsOnMethods = {"testActivateRule"}) + public void testDeleteRule() throws RuleManagementException { + + ruleManagementDAOImpl.deleteRule(createdRule.getId(), TENANT_ID); + Rule deletedRule = ruleManagementDAOImpl.getRuleByRuleId(createdRule.getId(), TENANT_ID); + assertNull(deletedRule); + } + + private static void assertExpressions(ANDCombinedRule andCombinedRule, Expression... expressions) { + + assertEquals(andCombinedRule.getExpressions().size(), expressions.length); + for (int i = 0; i < expressions.length; i++) { + assertEquals(andCombinedRule.getExpressions().get(i).getField(), expressions[i].getField()); + assertEquals(andCombinedRule.getExpressions().get(i).getOperator(), expressions[i].getOperator()); + assertEquals(andCombinedRule.getExpressions().get(i).getValue().getType(), + expressions[i].getValue().getType()); + assertEquals(andCombinedRule.getExpressions().get(i).getValue().getFieldValue(), + expressions[i].getValue().getFieldValue()); + } + } + + private static ANDCombinedRule assertAndCombinedRule(Rule andRule, int expectedExpressionsSize) { + + assertTrue(andRule instanceof ANDCombinedRule); + + ANDCombinedRule andCombinedRule = (ANDCombinedRule) andRule; + assertNotNull(andCombinedRule.getId()); + assertTrue(andCombinedRule.isActive()); + assertNotNull(andCombinedRule.getExpressions()); + assertEquals(andCombinedRule.getExpressions().size(), expectedExpressionsSize); + return andCombinedRule; + } + + private static ORCombinedRule assertOrCombinedRule(Rule rule, int expectedRulesSize) { + + assertTrue(rule instanceof ORCombinedRule); + ORCombinedRule orCombinedRule = (ORCombinedRule) rule; + assertNotNull(orCombinedRule.getRules()); + assertEquals(orCombinedRule.getRules().size(), expectedRulesSize); + return orCombinedRule; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/service/RuleManagementServiceImplTest.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/service/RuleManagementServiceImplTest.java new file mode 100644 index 000000000000..f32f420ff919 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/service/RuleManagementServiceImplTest.java @@ -0,0 +1,158 @@ +/* + * 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.rule.management.service; + +import org.mockito.MockedStatic; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; +import org.wso2.carbon.identity.common.testng.WithRealmService; +import org.wso2.carbon.identity.core.internal.IdentityCoreServiceDataHolder; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.rule.management.dao.RuleManagementDAO; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementClientException; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementException; +import org.wso2.carbon.identity.rule.management.model.Rule; +import org.wso2.carbon.identity.rule.management.service.impl.RuleManagementServiceImpl; + +import java.lang.reflect.Field; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; + +@WithCarbonHome +@WithRealmService(injectToSingletons = {IdentityCoreServiceDataHolder.class}) +public class RuleManagementServiceImplTest { + + private RuleManagementServiceImpl ruleManagementService; + private RuleManagementDAO ruleManagementDAO; + + private MockedStatic identityTenantUtilMockedStatic; + + public static final String RULE_ID = "ruleId"; + public static final String TENANT_DOMAIN = "test.com"; + public static final int TENANT_ID = 1; + + @BeforeClass + public void setUpClass() { + + ruleManagementService = RuleManagementServiceImpl.getInstance(); + + identityTenantUtilMockedStatic = mockStatic(IdentityTenantUtil.class); + when(IdentityTenantUtil.getTenantId(TENANT_DOMAIN)).thenReturn(TENANT_ID); + } + + @AfterClass + public void tearDownClass() { + + identityTenantUtilMockedStatic.close(); + } + + @BeforeMethod + public void setUp() throws Exception { + + ruleManagementDAO = mock(RuleManagementDAO.class); + Field daoField = RuleManagementServiceImpl.class.getDeclaredField("ruleManagementDAO"); + daoField.setAccessible(true); + daoField.set(ruleManagementService, ruleManagementDAO); + } + + @Test + public void testAddRule() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(rule); + + Rule result = ruleManagementService.addRule(rule, TENANT_DOMAIN); + + verify(ruleManagementDAO).addRule(rule, TENANT_ID); + verify(ruleManagementDAO).getRuleByRuleId(RULE_ID, TENANT_ID); + + assertEquals(result, rule); + } + + @Test + public void testUpdateRule() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(rule); + + Rule result = ruleManagementService.updateRule(rule, TENANT_DOMAIN); + + verify(ruleManagementDAO).updateRule(rule, TENANT_ID); + verify(ruleManagementDAO, times(2)).getRuleByRuleId(RULE_ID, TENANT_ID); + assertEquals(result, rule); + } + + @Test + public void testDeleteRule() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(rule); + + ruleManagementService.deleteRule(RULE_ID, TENANT_DOMAIN); + + verify(ruleManagementDAO).deleteRule(RULE_ID, TENANT_ID); + } + + @Test + public void testGetRuleByRuleId() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(rule); + + Rule result = ruleManagementService.getRuleByRuleId(RULE_ID, TENANT_DOMAIN); + + verify(ruleManagementDAO).getRuleByRuleId(RULE_ID, TENANT_ID); + assertEquals(result, rule); + } + + @Test + public void testDeactivateRule() throws RuleManagementException { + + Rule rule = mock(Rule.class); + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(rule); + + Rule result = ruleManagementService.deactivateRule(RULE_ID, TENANT_DOMAIN); + + verify(ruleManagementDAO).deactivateRule(RULE_ID, TENANT_ID); + verify(ruleManagementDAO, times(2)).getRuleByRuleId(RULE_ID, TENANT_ID); + assertEquals(result, rule); + } + + @Test(expectedExceptions = RuleManagementClientException.class, expectedExceptionsMessageRegExp = + "Rule not found for the given rule id: " + RULE_ID) + public void testUpdateIfRuleNotExist() throws RuleManagementException { + + when(ruleManagementDAO.getRuleByRuleId(RULE_ID, TENANT_ID)).thenReturn(null); + + Rule rule = mock(Rule.class); + when(rule.getId()).thenReturn(RULE_ID); + ruleManagementService.updateRule(rule, TENANT_DOMAIN); + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/util/RuleBuilderTest.java b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/util/RuleBuilderTest.java new file mode 100644 index 000000000000..dc8751dc2d91 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/util/RuleBuilderTest.java @@ -0,0 +1,476 @@ +/* + * 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.rule.management.util; + +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementClientException; +import org.wso2.carbon.identity.rule.management.exception.RuleManagementServerException; +import org.wso2.carbon.identity.rule.management.internal.RuleManagementComponentServiceHolder; +import org.wso2.carbon.identity.rule.management.model.Expression; +import org.wso2.carbon.identity.rule.management.model.FlowType; +import org.wso2.carbon.identity.rule.management.model.Rule; +import org.wso2.carbon.identity.rule.management.model.Value; +import org.wso2.carbon.identity.rule.management.model.internal.ANDCombinedRule; +import org.wso2.carbon.identity.rule.management.model.internal.ORCombinedRule; +import org.wso2.carbon.identity.rule.metadata.config.OperatorConfig; +import org.wso2.carbon.identity.rule.metadata.config.RuleMetadataConfigFactory; +import org.wso2.carbon.identity.rule.metadata.exception.RuleMetadataException; +import org.wso2.carbon.identity.rule.metadata.model.Field; +import org.wso2.carbon.identity.rule.metadata.model.FieldDefinition; +import org.wso2.carbon.identity.rule.metadata.model.Link; +import org.wso2.carbon.identity.rule.metadata.model.Operator; +import org.wso2.carbon.identity.rule.metadata.model.OptionsInputValue; +import org.wso2.carbon.identity.rule.metadata.model.OptionsReferenceValue; +import org.wso2.carbon.identity.rule.metadata.model.OptionsValue; +import org.wso2.carbon.identity.rule.metadata.service.RuleMetadataService; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +public class RuleBuilderTest { + + @Mock + RuleMetadataService ruleMetadataService; + private MockedStatic ruleMetadataConfigFactoryMockedStatic; + OperatorConfig operatorConfig; + + @BeforeClass + public void setUpClass() throws Exception { + + String filePath = Objects.requireNonNull(getClass().getClassLoader().getResource( + "configs/valid-operators.json")).getFile(); + operatorConfig = OperatorConfig.load(new File(filePath)); + } + + @BeforeMethod + public void setUpMethod() { + + ruleMetadataConfigFactoryMockedStatic = mockStatic(RuleMetadataConfigFactory.class); + ruleMetadataConfigFactoryMockedStatic.when(RuleMetadataConfigFactory::getOperatorConfig) + .thenReturn(operatorConfig); + + MockitoAnnotations.openMocks(this); + RuleManagementComponentServiceHolder.getInstance().setRuleMetadataService(ruleMetadataService); + } + + @AfterMethod + public void tearDownMethod() { + + ruleMetadataConfigFactoryMockedStatic.close(); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Expression metadata from RuleMetadataService is null or empty.") + public void testCreateRuleBuilderWhenExpressionMetaReturnedFromMetadataServiceIsNull() + throws Exception { + + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + null); + + RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Expression metadata from RuleMetadataService is null or empty.") + public void testCreateRuleBuilderWhenExpressionMetaReturnedFromMetadataServiceIsEmpty() + throws Exception { + + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + Collections.emptyList()); + + RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + } + + @Test(expectedExceptions = RuleManagementServerException.class, + expectedExceptionsMessageRegExp = "Error while retrieving expression metadata from RuleMetadataService.") + public void testCreateRuleBuilderWhenMetadataServiceThrowsException() + throws Exception { + + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenThrow( + new RuleMetadataException("RULEMETA-60005", "Error while retrieving expression metadata.", + "Failed to load data from configurations.")); + + RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + } + + @Test + public void testCreateRuleBuilder() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + assertNotNull(ruleBuilder); + } + + @Test + public void testCreateRuleWithValidExpressions() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression1 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp")).build(); + ruleBuilder.addAndExpression(expression1); + + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "authorization_code")).build(); + ruleBuilder.addAndExpression(expression2); + Rule rule = ruleBuilder.build(); + + assertNotNull(rule); + assertNotNull(rule.getId()); + assertTrue(rule.isActive()); + + ORCombinedRule orCombinedRule = assertOrCombinedRule(rule, 1); + + orCombinedRule.getRules() + .forEach(andRule -> assertExpressions(assertAndCombinedRule(andRule, 2), expression1, expression2)); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Field invalid is not supported") + public void testCreateRuleWithAnExpressionWithInvalidField() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression = new Expression.Builder().field("invalid").operator("equals") + .value(new Value(Value.Type.STRING, "value")).build(); + ruleBuilder.addAndExpression(expression); + + ruleBuilder.build(); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Operator invalid is not supported for field application") + public void testCreateRuleWithAnExpressionWithInvalidOperator() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")) + .thenReturn(mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression = new Expression.Builder().field("application").operator("invalid") + .value(new Value(Value.Type.STRING, "value")).build(); + ruleBuilder.addAndExpression(expression); + + ruleBuilder.build(); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Value invalid is not supported for field grantType") + public void testCreateRuleWithAnExpressionWithInvalidValue() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")) + .thenReturn(mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "invalid")).build(); + ruleBuilder.addAndExpression(expression); + + ruleBuilder.build(); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Value type STRING is not supported for field application") + public void testCreateRuleWithAnExpressionWithInvalidValueType() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")) + .thenReturn(mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.STRING, "testapp")).build(); + ruleBuilder.addAndExpression(expression); + + ruleBuilder.build(); + } + + /** + * This test case is to test the scenario where multiple validation failures occur when building a rule. + * In this case, only the very first validation failure is expected to be thrown. + * + * @throws Exception Client exception when building the rule + */ + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Field invalid is not supported") + public void testCreateRuleWithMultipleValidationFailures() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")) + .thenReturn(mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + // Expression with invalid field + Expression expression1 = new Expression.Builder().field("invalid").operator("equals") + .value(new Value(Value.Type.STRING, "value")).build(); + ruleBuilder.addAndExpression(expression1); + + // Expression with invalid operator + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "invalid")).build(); + ruleBuilder.addAndExpression(expression2); + + ruleBuilder.addOrCondition(); + + // Expression with invalid value type + Expression expression3 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.STRING, "testapp")).build(); + ruleBuilder.addAndExpression(expression3); + + ruleBuilder.build(); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Maximum number of expressions combined with AND exceeded. Maximum allowed: 5 Provided: 6") + public void testCreateRuleWithMaxAllowedExpressionsCombinedWithAND() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + for (int i = 0; i < 6; i++) { + Expression expression = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp" + i)).build(); + ruleBuilder.addAndExpression(expression); + } + + ruleBuilder.build(); + } + + @Test(expectedExceptions = RuleManagementClientException.class, + expectedExceptionsMessageRegExp = "Building rule failed due to validation errors. " + + "Error: Maximum number of rules combined with OR exceeded. Maximum allowed: 10 Provided: 11") + public void testCreateRuleWithMaxAllowedRulesCombinedWithOR() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + for (int i = 0; i < 11; i++) { + Expression expression = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp" + i)).build(); + ruleBuilder.addAndExpression(expression); + ruleBuilder.addOrCondition(); + } + + ruleBuilder.build(); + } + + @Test + public void testCreateRuleWithValidExpressionsAndOR() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression1 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + ruleBuilder.addAndExpression(expression1); + + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "authorization_code")).build(); + ruleBuilder.addAndExpression(expression2); + + ruleBuilder.addOrCondition(); + + Expression expression3 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp2")).build(); + ruleBuilder.addAndExpression(expression3); + + Rule rule = ruleBuilder.build(); + + assertNotNull(rule); + assertNotNull(rule.getId()); + assertTrue(rule.isActive()); + + ORCombinedRule orCombinedRule = assertOrCombinedRule(rule, 2); + ANDCombinedRule andCombinedRule = assertAndCombinedRule(orCombinedRule.getRules().get(0), 2); + assertExpressions(andCombinedRule, expression1, expression2); + + andCombinedRule = assertAndCombinedRule(orCombinedRule.getRules().get(1), 1); + assertExpressions(andCombinedRule, expression3); + } + + @Test + public void testCreateRuleWithMultipleExpressionsUsingSameFieldReferenceAndOR() throws Exception { + + List mockedFieldDefinitions = getMockedFieldDefinitions(); + when(ruleMetadataService.getExpressionMeta( + org.wso2.carbon.identity.rule.metadata.model.FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1")).thenReturn( + mockedFieldDefinitions); + + RuleBuilder ruleBuilder = RuleBuilder.create(FlowType.PRE_ISSUE_ACCESS_TOKEN, "tenant1"); + + Expression expression1 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + ruleBuilder.addAndExpression(expression1); + + Expression expression2 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "authorization_code")).build(); + ruleBuilder.addAndExpression(expression2); + + ruleBuilder.addOrCondition(); + + Expression expression3 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp1")).build(); + ruleBuilder.addAndExpression(expression3); + + Expression expression4 = new Expression.Builder().field("grantType").operator("equals") + .value(new Value(Value.Type.STRING, "client_credentials")).build(); + ruleBuilder.addAndExpression(expression4); + + ruleBuilder.addOrCondition(); + + Expression expression5 = new Expression.Builder().field("application").operator("equals") + .value(new Value(Value.Type.REFERENCE, "testapp2")).build(); + ruleBuilder.addAndExpression(expression5); + + Rule rule = ruleBuilder.build(); + + assertNotNull(rule); + assertNotNull(rule.getId()); + assertTrue(rule.isActive()); + + ORCombinedRule orCombinedRule = assertOrCombinedRule(rule, 3); + ANDCombinedRule andCombinedRule = assertAndCombinedRule(orCombinedRule.getRules().get(0), 2); + assertExpressions(andCombinedRule, expression1, expression2); + + andCombinedRule = assertAndCombinedRule(orCombinedRule.getRules().get(1), 2); + assertExpressions(andCombinedRule, expression3, expression4); + + andCombinedRule = assertAndCombinedRule(orCombinedRule.getRules().get(2), 1); + assertExpressions(andCombinedRule, expression5); + } + + private List getMockedFieldDefinitions() { + + List fieldDefinitionList = new ArrayList<>(); + + Field applicationField = new Field("application", "application"); + List operators = Arrays.asList(new Operator("equals", "equals"), + new Operator("notEquals", "not equals")); + + List links = Arrays.asList(new Link("/applications?offset=0&limit=10", "GET", "values"), + new Link("/applications?filter=name+eq+*&limit=10", "GET", "filter")); + org.wso2.carbon.identity.rule.metadata.model.Value + applicationValue = new OptionsReferenceValue.Builder().valueReferenceAttribute("id") + .valueDisplayAttribute("name").valueType( + org.wso2.carbon.identity.rule.metadata.model.Value.ValueType.REFERENCE).links(links).build(); + fieldDefinitionList.add(new FieldDefinition(applicationField, operators, applicationValue)); + + Field grantTypeField = new Field("grantType", "grantType"); + List optionsValues = Arrays.asList(new OptionsValue("authorization_code", "authorization code"), + new OptionsValue("password", "password"), new OptionsValue("refresh_token", "refresh token"), + new OptionsValue("client_credentials", "client credentials"), + new OptionsValue("urn:ietf:params:oauth:grant-type:token-exchange", "token exchange")); + org.wso2.carbon.identity.rule.metadata.model.Value + grantTypeValue = + new OptionsInputValue(org.wso2.carbon.identity.rule.metadata.model.Value.ValueType.STRING, + optionsValues); + fieldDefinitionList.add(new FieldDefinition(grantTypeField, operators, grantTypeValue)); + + return fieldDefinitionList; + } + + private static void assertExpressions(ANDCombinedRule andCombinedRule, Expression... expressions) { + + assertEquals(andCombinedRule.getExpressions().size(), expressions.length); + for (int i = 0; i < expressions.length; i++) { + assertEquals(andCombinedRule.getExpressions().get(i), expressions[i]); + } + } + + private static ANDCombinedRule assertAndCombinedRule(Rule andRule, int expectedExpressionsSize) { + + assertTrue(andRule instanceof ANDCombinedRule); + + ANDCombinedRule andCombinedRule = (ANDCombinedRule) andRule; + assertNotNull(andCombinedRule.getId()); + assertTrue(andCombinedRule.isActive()); + assertNotNull(andCombinedRule.getExpressions()); + assertEquals(andCombinedRule.getExpressions().size(), expectedExpressionsSize); + return andCombinedRule; + } + + private static ORCombinedRule assertOrCombinedRule(Rule rule, int expectedRulesSize) { + + assertTrue(rule instanceof ORCombinedRule); + ORCombinedRule orCombinedRule = (ORCombinedRule) rule; + assertNotNull(orCombinedRule.getRules()); + assertEquals(orCombinedRule.getRules().size(), expectedRulesSize); + return orCombinedRule; + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/configs/valid-operators.json b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/configs/valid-operators.json new file mode 100644 index 000000000000..440832b8f460 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/configs/valid-operators.json @@ -0,0 +1,14 @@ +{ + "equals": { + "name": "equals", + "displayName": "equals" + }, + "notEquals": { + "name": "notEquals", + "displayName": "not equals" + }, + "contains": { + "name": "contains", + "displayName": "contains" + } +} diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/dbscripts/h2.sql b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/dbscripts/h2.sql new file mode 100644 index 000000000000..6e6236d38fa6 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/dbscripts/h2.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS IDN_RULE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE BOOLEAN DEFAULT TRUE, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +); + +CREATE TABLE IF NOT EXISTS IDN_RULE_REFERENCES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +); diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/repository/conf/carbon.xml b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/repository/conf/carbon.xml new file mode 100644 index 000000000000..a5a1a6470cbc --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/repository/conf/carbon.xml @@ -0,0 +1,686 @@ + + + + + + + + WSO2 Identity Server + + + IS + + + 5.3.0 + + + localhost + + + localhost + + + local:/${carbon.context}/services/ + + + + + + + IdentityServer + + + + + + + org.wso2.carbon + + + / + + + + + + + + + 15 + + + + + + + + + 0 + + + + + 9999 + + 11111 + + + + + + 10389 + + 8000 + + + + + + 10500 + + + + + + + + + org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory + + + + + + + + + java + + + + + + + + + + false + + + false + + + 600 + + + + false + + + + + + + + 30 + + + + + + + + + 15 + + + + + + ${carbon.home}/repository/deployment/server/ + + + 15 + + + ${carbon.home}/repository/conf/axis2/axis2.xml + + + 30000 + + + ${carbon.home}/repository/deployment/client/ + + ${carbon.home}/repository/conf/axis2/axis2_client.xml + + true + + + + + + + + + + admin + Default Administrator Role + + + user + Default User Role + + + + + + + + + + + + ${carbon.home}/repository/resources/security/wso2carbon.jks + + JKS + + wso2carbon + + wso2carbon + + wso2carbon + + + + + + ${carbon.home}/repository/resources/security/client-truststore.jks + + JKS + + wso2carbon + + + + + + + + + + + + + + + + + + + UserManager + + + false + + org.wso2.carbon.identity.provider.AttributeCallbackHandler + + + org.wso2.carbon.identity.sts.store.DBTokenStore + + + true + allow + + + + + + + claim_mgt_menu + identity_mgt_emailtemplate_menu + identity_security_questions_menu + + + + ${carbon.home}/tmp/work + + + + + + true + + + 10 + + + 30 + + + + + + 100 + + + + keystore + certificate + * + + org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor + + + + + jarZip + + org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor + + + + dbs + + org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor + + + + tools + + org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor + + + + toolsAny + + org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor + + + + + + + + + + info + org.wso2.carbon.core.transports.util.InfoProcessor + + + wsdl + org.wso2.carbon.core.transports.util.Wsdl11Processor + + + wsdl2 + org.wso2.carbon.core.transports.util.Wsdl20Processor + + + xsd + org.wso2.carbon.core.transports.util.XsdProcessor + + + + + + false + false + true + svn + http://svnrepo.example.com/repos/ + username + password + true + + + + + + + + + + + + + + + ${require.carbon.servlet} + + + + + true + + + + + + + default repository + http://product-dist.wso2.com/p2/carbon/releases/wilkes/ + + + + + + + + true + + + + + + true + + diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/repository/conf/identity/identity.xml b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/repository/conf/identity/identity.xml new file mode 100644 index 000000000000..07de6831dbf4 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/repository/conf/identity/identity.xml @@ -0,0 +1,743 @@ + + + + + + + + + jdbc/WSO2IdentityDB + + + + + true + true + 0 + + true + 20160 + 1140 + + + true + 720 + + + + + + + 15 + 20160 + + + + + + ${carbon.home}/conf/keystores + SunX509 + SunX509 + + + + SelfAndManaged + CertValidate + + + + + + + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/openidserver + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/openid + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/openid_login.do + + + false + + 7200 + + false + + + + + + + + + + + + + + + + + + + + + + -1 + -1 + -1 + -1 + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/request-token + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/authorize-url + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth/access-token + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/authorize + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/revoke + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/introspect + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/userinfo + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oidc/checksession + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oidc/logout + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_authz.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_error.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_consent.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_logout_consent.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/oauth2_logout.do + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/.well-known/webfinger + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/identity/connect/register + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/jwks + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/oidcdiscovery + + + 300 + + 3600 + + 3600 + + 84600 + + 300 + + false + + true + + org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor + + + + false + + + + + + token + org.wso2.carbon.identity.oauth2.authz.handlers.AccessTokenResponseTypeHandler + + + code + org.wso2.carbon.identity.oauth2.authz.handlers.CodeResponseTypeHandler + + + id_token + org.wso2.carbon.identity.oauth2.authz.handlers.IDTokenResponseTypeHandler + + + id_token token + org.wso2.carbon.identity.oauth2.authz.handlers.IDTokenTokenResponseTypeHandler + + + + + + authorization_code + org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationCodeGrantHandler + + + password + org.wso2.carbon.identity.oauth2.token.handlers.grant.PasswordGrantHandler + + + refresh_token + org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler + + + client_credentials + org.wso2.carbon.identity.oauth2.token.handlers.grant.ClientCredentialsGrantHandler + + + urn:ietf:params:oauth:grant-type:saml2-bearer + org.wso2.carbon.identity.oauth2.token.handlers.grant.saml.SAML2BearerGrantHandler + + + iwa:ntlm + org.wso2.carbon.identity.oauth2.token.handlers.grant.iwa.ntlm.NTLMAuthenticationGrantHandler + + + idTokenNotAllowedGrantType + org.wso2.carbon.identity.oauth2.token.handlers.grant.idTokenNotAllowedGrantHandler + false + + + + + + + + + false + + + + false + + + + false + org.wso2.carbon.identity.oauth2.authcontext.JWTTokenGenerator + org.wso2.carbon.identity.oauth2.authcontext.DefaultClaimsRetriever + http://wso2.org/claims + SHA256withRSA + 10 + + + + + + org.wso2.carbon.identity.openidconnect.DefaultIDTokenBuilder + SHA256withRSA + + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token + org.wso2.carbon.identity.openidconnect.DefaultOIDCClaimsCallbackHandler + 3600 + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoUserStoreClaimRetriever + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInforRequestDefaultValidator + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoISAccessTokenValidator + org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoJSONResponseBuilder + false + + + + + + + + gtalk + talk.google.com + 5222 + gmail.com + multifactor1@gmail.com + wso2carbon + + + + + + 157680000 + 157680000 + ${carbon.host} + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/samlsso + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/samlsso_logout.do + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/samlsso_notification.do + 5 + 60000 + + false + http://wso2.org/claims + org.wso2.carbon.identity.sso.saml.builders.assertion.ExtendedDefaultAssertionBuilder + + org.wso2.carbon.identity.sso.saml.builders.encryption.DefaultSSOEncrypter + org.wso2.carbon.identity.sso.saml.builders.signature.DefaultSSOSigner + org.wso2.carbon.identity.sso.saml.validators.SAML2HTTPRedirectDeflateSignatureValidator + + + + 5 + false + http://www.w3.org/2000/09/xmldsig#rsa-sha1 + http://www.w3.org/2000/09/xmldsig#sha1 + true + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/services/wso2carbon-sts + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/passivests + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/authenticationendpoint/retry.do + org.wso2.carbon.identity.sts.passive.utils.NoPersistenceTokenStore + true + + + + + false + ${Ports.ThriftEntitlementReceivePort} + 10000 + + ${carbon.home}/repository/resources/security/wso2carbon.jks + wso2carbon + + + ${carbon.host} + + + + + + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2/scim/Users + ${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2/scim/Groups + + + 5 + + + 10 + local://services + + + + + + + + + + + + + org.wso2.carbon.identity.governance.store.JDBCIdentityDataStore + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /permission/admin/manage/identity/identitymgt + + + + + + /permission/admin/manage/identity/usermgt/view + + + /permission/admin/manage/identity/usermgt/view + + + + /permission/admin/manage/identity/configmgt/list + + + + /permission/admin/manage/identity/configmgt/add + + + /permission/admin/manage/identity/configmgt/update + + + + /permission/admin/manage/identity/configmgt/delete + + + + /permission/admin/manage/identity/configmgt/add + + + /permission/admin/manage/identity/configmgt/update + + + + /permission/admin/manage/identity/configmgt/delete + + + + /permission/admin/manage/identity/configmgt/add + + + /permission/admin/manage/identity/configmgt/update + + + + /permission/admin/manage/identity/configmgt/delete + + + + + + + /permission/admin/manage/identity/consentmgt/add + + + + /permission/admin/manage/identity/consentmgt/delete + + + + /permission/admin/manage/identity/consentmgt/add + + + + /permission/admin/manage/identity/consentmgt/delete + + + + /permission/admin/manage/identity/consentmgt/add + + + + /permission/admin/manage/identity/consentmgt/delete + + + + /permission/admin/manage/identity/identitymgt + + + + /permission/admin/manage/identity/applicationmgt/create + + + /permission/admin/manage/identity/applicationmgt/delete + + + /permission/admin/manage/identity/applicationmgt/update + + + /permission/admin/manage/identity/applicationmgt/view + + + /permission/admin/manage/identity/applicationmgt/delete + + + /permission/admin/manage/identity/applicationmgt/create + + + /permission/admin/manage/identity/applicationmgt/view + + + /permission/admin/manage/identity/pep + + + /permission/admin/manage/identity/usermgt/create + + + /permission/admin/manage/identity/usermgt/list + + + /permission/admin/manage/identity/rolemgt/create + + + /permission/admin/manage/identity/rolemgt/view + + + /permission/admin/manage/identity/usermgt/view + + + /permission/admin/manage/identity/usermgt/update + + + /permission/admin/manage/identity/usermgt/update + + + /permission/admin/manage/identity/usermgt/delete + + + /permission/admin/manage/identity/rolemgt/view + + + /permission/admin/manage/identity/rolemgt/update + + + /permission/admin/manage/identity/rolemgt/update + + + /permission/admin/manage/identity/rolemgt/delete + + + /permission/admin/login + + + /permission/admin/manage/identity/usermgt/delete + + + /permission/admin/login + + + /permission/admin/login + + + /permission/admin/manage/identity/usermgt/create + + + + + + + + + /permission/admin/manage/identity/usermgt + + + /permission/admin/manage/identity/applicationmgt + + + + + + + /permission/admin/manage/identity/usermgt/update + + + + + + /permission/admin/manage/humantask/viewtasks + + + /permission/admin/login + + + /permission/admin/manage/identity/usermgt + + + /permission/admin/manage/identity/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /api/identity/user/v0.9 + /api/identity/recovery/v0.9 + /oauth2 + /api/identity/entitlement + + + /identity/(.*) + + + + + + applications,connections + + + + 300 + diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/testng.xml b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/testng.xml new file mode 100644 index 000000000000..90613c3d2d42 --- /dev/null +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/testng.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/rule-mgt/org.wso2.carbon.identity.rule.metadata/pom.xml b/components/rule-mgt/org.wso2.carbon.identity.rule.metadata/pom.xml index 6f0f1351e7bb..3e604d02bac7 100644 --- a/components/rule-mgt/org.wso2.carbon.identity.rule.metadata/pom.xml +++ b/components/rule-mgt/org.wso2.carbon.identity.rule.metadata/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework rule-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/rule-mgt/pom.xml b/components/rule-mgt/pom.xml index cc8eb542c472..16ff303f7dd7 100644 --- a/components/rule-mgt/pom.xml +++ b/components/rule-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/secret-mgt/org.wso2.carbon.identity.secret.mgt.core/pom.xml b/components/secret-mgt/org.wso2.carbon.identity.secret.mgt.core/pom.xml index 907562af8fa1..2df8925fe848 100644 --- a/components/secret-mgt/org.wso2.carbon.identity.secret.mgt.core/pom.xml +++ b/components/secret-mgt/org.wso2.carbon.identity.secret.mgt.core/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework secret-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT 4.0.0 diff --git a/components/secret-mgt/pom.xml b/components/secret-mgt/pom.xml index b78e5930f94d..a8038a110936 100644 --- a/components/secret-mgt/pom.xml +++ b/components/secret-mgt/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/security-mgt/org.wso2.carbon.security.mgt.ui/pom.xml b/components/security-mgt/org.wso2.carbon.security.mgt.ui/pom.xml index 96f38184c0e7..a9adc994de5d 100644 --- a/components/security-mgt/org.wso2.carbon.security.mgt.ui/pom.xml +++ b/components/security-mgt/org.wso2.carbon.security.mgt.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework security-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/pom.xml b/components/security-mgt/org.wso2.carbon.security.mgt/pom.xml index 55dae011155d..bd02eaa3fdac 100644 --- a/components/security-mgt/org.wso2.carbon.security.mgt/pom.xml +++ b/components/security-mgt/org.wso2.carbon.security.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework security-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml @@ -106,6 +106,14 @@ org.wso2.orbit.javax.xml.bind jaxb-api
+ + org.wso2.orbit.org.bouncycastle + bcpkix-jdk18on + + + org.wso2.orbit.org.bouncycastle + bcprov-jdk18on + @@ -156,7 +164,8 @@ org.wso2.carbon.registry.core.*;version="${carbon.kernel.registry.imp.pkg.version}", org.wso2.carbon.registry.api;version="${carbon.kernel.registry.imp.pkg.version}", org.wso2.carbon.identity.core.*; version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.identity.base; version="${carbon.identity.package.import.version.range}" + org.wso2.carbon.identity.base; version="${carbon.identity.package.import.version.range}", + org.bouncycastle.*;version="${org.bouncycastle.imp.pkg.version.range}", !org.wso2.carbon.security.internal, diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/SecurityConstants.java b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/SecurityConstants.java index 4f50c249076c..a5da81df780a 100644 --- a/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/SecurityConstants.java +++ b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/SecurityConstants.java @@ -131,7 +131,7 @@ public static class KeyStoreMgtConstants { public static final String FILTER_OPERATION_CONTAINS = "co"; public static final String SERVER_TRUSTSTORE_FILE = "Security.TrustStore.Location"; - + public static final String KEY_STORE_CONTEXT_SEPARATOR = "--"; /** * Enum for Keystore management service related errors. */ diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/internal/SecurityMgtServiceComponent.java b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/internal/SecurityMgtServiceComponent.java index fe1cea36fcaa..638d41d6d4af 100644 --- a/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/internal/SecurityMgtServiceComponent.java +++ b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/internal/SecurityMgtServiceComponent.java @@ -42,6 +42,8 @@ import org.wso2.carbon.security.SecurityServiceHolder; import org.wso2.carbon.security.keystore.KeyStoreManagementService; import org.wso2.carbon.security.keystore.KeyStoreManagementServiceImpl; +import org.wso2.carbon.security.keystore.service.IdentityKeyStoreGenerator; +import org.wso2.carbon.security.keystore.service.IdentityKeyStoreGeneratorImpl; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.ConfigurationContextService; @@ -66,6 +68,8 @@ protected void activate(ComponentContext ctxt) { BundleContext bundleCtx = ctxt.getBundleContext(); bundleCtx.registerService(KeyStoreManagementService.class.getName(), new KeyStoreManagementServiceImpl(), null); + bundleCtx.registerService(IdentityKeyStoreGenerator.class.getName(), new IdentityKeyStoreGeneratorImpl(), + null); try { addKeystores(); } catch (Exception e) { diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGenerator.java b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGenerator.java new file mode 100644 index 000000000000..4cc380c1462e --- /dev/null +++ b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGenerator.java @@ -0,0 +1,39 @@ +/* + * 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.security.keystore.service; + +import org.wso2.carbon.security.keystore.KeyStoreManagementException; + +/** + * Interface for generating and managing context-specific tenant key stores. + */ +public interface IdentityKeyStoreGenerator { + + /** + * Generates a context-specific KeyStore for a given tenant domain. + *

+ * This method creates a new KeyStore for the specified tenant domain and context if it does not already exist. + *

+ * + * @param tenantDomain the tenant domain for which the KeyStore is to be created. + * @param context the context for which the KeyStore is to be generated. + * @throws KeyStoreManagementException if an error occurs during KeyStore creation or initialization. + */ + void generateKeyStore(String tenantDomain, String context) throws KeyStoreManagementException; +} diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGeneratorImpl.java b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGeneratorImpl.java new file mode 100644 index 000000000000..22f75c7e6905 --- /dev/null +++ b/components/security-mgt/org.wso2.carbon.security.mgt/src/main/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGeneratorImpl.java @@ -0,0 +1,314 @@ +/* + * 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.security.keystore.service; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.wso2.carbon.base.ServerConfiguration; +import org.wso2.carbon.core.util.CryptoUtil; +import org.wso2.carbon.core.util.KeyStoreManager; +import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants; +import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverException; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.security.keystore.KeyStoreManagementException; +import org.wso2.carbon.utils.ServerConstants; +import org.wso2.carbon.utils.security.KeystoreUtils; + +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Date; + +import static org.wso2.carbon.security.SecurityConstants.KeyStoreMgtConstants.KEY_STORE_CONTEXT_SEPARATOR; + +/** + * Implementation of the {@link IdentityKeyStoreGenerator} interface for generating and managing + * context-specific tenant key stores. This class provides functionality to create, manage, and store + * keystores in a multi-tenant environment, adhering to specific cryptographic requirements. + * + *

Key Features:

+ *
    + *
  • Generates keystores for tenants dynamically.
  • + *
  • Supports various cryptographic algorithms and key generation techniques.
  • + *
  • Handles secure persistence of keystores using {@link KeyStoreManager}.
  • + *
  • Provides explainable methods for certificate creation, storage, and retrieval.
  • + *
+ * + *

Usage:

+ * This class is intended to be used in environments where context-specific cryptographic needs + * must be met dynamically. + * + *

Exceptions:

+ * The methods in this class throw {@link KeyStoreManagementException} for errors encountered during + * keystore creation, management, or persistence. + */ +public class IdentityKeyStoreGeneratorImpl implements IdentityKeyStoreGenerator { + + private static final Log LOG = LogFactory.getLog(IdentityKeyStoreGeneratorImpl.class); + private static final String SIGNING_ALG = "Tenant.SigningAlgorithm"; + + // Supported signature algorithms for public certificate generation. + private static final String RSA_MD5 = "MD5withRSA"; + private static final String RSA_SHA1 = "SHA1withRSA"; + private static final String RSA_SHA256 = "SHA256withRSA"; + private static final String RSA_SHA384 = "SHA384withRSA"; + private static final String RSA_SHA512 = "SHA512withRSA"; + private static final String[] signatureAlgorithms = new String[]{ + RSA_MD5, RSA_SHA1, RSA_SHA256, RSA_SHA384, RSA_SHA512 + }; + private static final long CERT_NOT_BEFORE_TIME = 1000L * 60 * 60 * 24 * 30; // 30 days in milliseconds + private static final long CERT_NOT_AFTER_TIME = 1000L * 60 * 60 * 24 * 365 * 10; // 10 years in milliseconds + + /** + * Generates a context-specific KeyStore for a given tenant domain if it does not already exist. + *

+ * This method checks whether a KeyStore exists for the specified tenant domain and context. + * If the KeyStore does not exist, it creates a new one, initializes it, generates the necessary + * key pairs, and persists it. + *

+ * + * @param tenantDomain the tenant domain for which the KeyStore is to be generated. + * @param context the specific context for which the KeyStore is to be generated. + * @throws KeyStoreManagementException if an error occurs during the KeyStore creation or initialization. + */ + public void generateKeyStore(String tenantDomain, String context) throws KeyStoreManagementException { + + int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); + KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); + + try { + IdentityTenantUtil.initializeRegistry(tenantId); + if (isContextKeyStoreExists(context, tenantDomain, keyStoreManager)) { + return; // KeyStore already exists, no need to create again + } + // Create the KeyStore + String password = generatePassword(); + KeyStore keyStore = KeystoreUtils.getKeystoreInstance( + KeystoreUtils.getKeyStoreFileType(tenantDomain)); + keyStore.load(null, password.toCharArray()); + generateContextKeyPair(keyStore, context, tenantDomain, password); + persistContextKeyStore(keyStore, context, tenantDomain, password, keyStoreManager); + } catch (Exception e) { + String msg = "Error while instantiating a keystore"; + throw new KeyStoreManagementException(msg, e); + } + } + + private boolean isContextKeyStoreExists(String context, String tenantDomain, KeyStoreManager keyStoreManager) + throws KeyStoreManagementException { + + String keyStoreName = KeystoreUtils.getKeyStoreFileLocation(buildDomainWithContext(tenantDomain, context)); + boolean isKeyStoreExists = false; + try { + keyStoreManager.getKeyStore(keyStoreName); + isKeyStoreExists = true; + } catch (SecurityException e) { + if (e.getMessage() != null && e.getMessage().contains("Key Store with a name: " + keyStoreName + + " does not exist.")) { + + String msg = "Key store not exits. Proceeding to create keystore : " + keyStoreName; + LOG.debug(msg + e.getMessage()); + } else { + String msg = "Error while checking the existence of keystore."; + throw new KeyStoreManagementException(msg, e); + } + } catch (Exception e) { + String msg = "Error while checking the existence of keystore."; + throw new KeyStoreManagementException(msg, e); + } + return isKeyStoreExists; + } + + /** + * This method is used to generate a random password for the generated keystore + * + * @return generated password + */ + private String generatePassword() { + + SecureRandom random = new SecureRandom(); + String randString = new BigInteger(130, random).toString(12); + return randString.substring(randString.length() - 10); + } + + /** + * Persists a context-specific KeyStore for a given tenant domain. + *

+ * This method stores the provided KeyStore in a persistent storage using the {@code KeyStoreManager}. + * It generates a KeyStore name based on the tenant domain and context, converts the KeyStore + * into a byte array, and saves it securely along with the provided password. + *

+ * + * @param keyStore the KeyStore to be persisted. + * @param context the specific context for which the KeyStore is being persisted. + * @param tenantDomain the tenant domain associated with the KeyStore. + * @param password the password used to protect the KeyStore. + * @param keyStoreManager the {@code KeyStoreManager} instance responsible for managing the persistence of the KeyStore. + * @throws KeyStoreManagementException if an error occurs while persisting the KeyStore or if security issues arise. + */ + private void persistContextKeyStore(KeyStore keyStore, String context, String tenantDomain, String password, + KeyStoreManager keyStoreManager) throws KeyStoreManagementException { + + String keyStoreName = generateContextKSNameFromDomainName(context, tenantDomain); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + char[] passwordChar = password.toCharArray(); + try { + keyStore.store(outputStream, passwordChar); + outputStream.flush(); + outputStream.close(); + } catch (Exception e) { + String msg = "Error occurred while storing the keystore or processing the public certificate for tenant: " + + tenantDomain + " and context: " + context + ". Ensure the keystore is valid and writable."; + throw new KeyStoreManagementException(msg, e); + } + + try { + + keyStoreManager.addKeyStore(outputStream.toByteArray(), keyStoreName, + passwordChar, " ", KeystoreUtils.getKeyStoreFileType(tenantDomain), passwordChar); + } catch (SecurityException e) { + if (e.getMessage() != null && e.getMessage().contains("Key store " + keyStoreName + " already available")) { + + LOG.warn("Key store " + keyStoreName + " is already available, ignoring."); + } else { + + String msg = "Error when adding a keyStore"; + throw new KeyStoreManagementException(msg, e); + } + } + } + + /** + * This method generates the keypair and stores it in the keystore. + * + * @param keyStore the KeyStore to be persisted. + * @param context the specific context for which the KeyStore is being persisted. + * @param tenantDomain the tenant domain associated with the KeyStore. + * @param password the password used to protect the KeyStore. + * @throws KeyStoreManagementException Error when generating key pair + */ + private void generateContextKeyPair(KeyStore keyStore, String context, String tenantDomain, String password) + throws KeyStoreManagementException { + + try { + CryptoUtil.getDefaultCryptoUtil(); + // Generate key pair + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + + // Common Name and alias for the generated certificate + String commonName = "CN=" + buildDomainWithContext(tenantDomain, context) + + ", OU=None, O=None, L=None, C=None"; + + // Generate certificates + X500Name distinguishedName = new X500Name(commonName); + + Date notBefore = new Date(System.currentTimeMillis() - CERT_NOT_BEFORE_TIME); + Date notAfter = new Date(System.currentTimeMillis() + CERT_NOT_AFTER_TIME); + + SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()); + BigInteger serialNumber = BigInteger.valueOf(new SecureRandom().nextInt()); + + X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder( + distinguishedName, + serialNumber, + notBefore, + notAfter, + distinguishedName, + subPubKeyInfo + ); + + String algorithmName = getSignatureAlgorithm(); + JcaContentSignerBuilder signerBuilder = + new JcaContentSignerBuilder(algorithmName).setProvider(getJCEProvider()); + PrivateKey privateKey = keyPair.getPrivate(); + X509Certificate x509Cert = new JcaX509CertificateConverter().setProvider(getJCEProvider()) + .getCertificate(certificateBuilder.build(signerBuilder.build(privateKey))); + + // Add private key to KS + keyStore.setKeyEntry(buildDomainWithContext(tenantDomain, context), + keyPair.getPrivate(), password.toCharArray(), + new java.security.cert.Certificate[]{x509Cert}); + } catch (Exception ex) { + String msg = "Error while generating the Context certificate for tenant :" + + tenantDomain + "."; + throw new KeyStoreManagementException(msg, ex); + } + } + + private static String getSignatureAlgorithm() { + + String algorithm = ServerConfiguration.getInstance().getFirstProperty(SIGNING_ALG); + // Find in a list of supported signature algorithms. + for (String supportedAlgorithm : signatureAlgorithms) { + if (supportedAlgorithm.equalsIgnoreCase(algorithm)) { + return supportedAlgorithm; + } + } + return RSA_MD5; + } + + private static String getJCEProvider() { + + String provider = ServerConfiguration.getInstance().getFirstProperty(ServerConstants.JCE_PROVIDER); + if (!StringUtils.isBlank(provider)) { + return provider; + } + return ServerConstants.JCE_PROVIDER_BC; + } + + /** + * This method generates the key store file name from the Domain Name + * @return keystore name. + */ + private String generateContextKSNameFromDomainName(String context, String tenantDomain) + throws KeyStoreManagementException { + + String ksName = tenantDomain.trim().replace(".", "-"); + ksName = buildDomainWithContext(ksName, context); + return (ksName + KeystoreUtils.getKeyStoreFileExtension(tenantDomain)); + } + + /** + * Concatenates ksName and context with the separator. + * + * @param ksName the key store name + * @param context the context + * @return a concatenated string in the format ksName:context + */ + private String buildDomainWithContext(String ksName, String context) throws KeyStoreManagementException { + + if (ksName == null || context == null) { + throw new KeyStoreManagementException("ksName and context must not be null"); + } + return ksName + KEY_STORE_CONTEXT_SEPARATOR + context; + } +} diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/test/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGeneratorImplTest.java b/components/security-mgt/org.wso2.carbon.security.mgt/src/test/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGeneratorImplTest.java new file mode 100644 index 000000000000..a8dfb803f402 --- /dev/null +++ b/components/security-mgt/org.wso2.carbon.security.mgt/src/test/java/org/wso2/carbon/security/keystore/service/IdentityKeyStoreGeneratorImplTest.java @@ -0,0 +1,260 @@ +/* + * 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.security.keystore.service; + +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.stubbing.Answer; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.*; +import org.wso2.carbon.base.CarbonBaseConstants; +import org.wso2.carbon.core.util.KeyStoreManager; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.testutil.IdentityBaseTest; +import org.wso2.carbon.security.keystore.KeyStoreManagementException; +import org.wso2.carbon.utils.security.KeystoreUtils; + +import java.io.FileInputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.Security; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@Listeners(MockitoTestNGListener.class) +public class IdentityKeyStoreGeneratorImplTest extends IdentityBaseTest { + + private static final String KEYSTORE_PASSWORD = "wso2carbon"; + + private IdentityKeyStoreGeneratorImpl identityKeyStoreGenerator; + + private MockedStatic identityTenantUtil; + @Mock + private KeyStoreManager keyStoreManager; + + @Mock + private KeyStore mockKeyStore; + + + @BeforeMethod + public void setUp() throws Exception { + + if (Security.getProvider("BC") == null) { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + + System.setProperty( + CarbonBaseConstants.CARBON_HOME, + Paths.get(System.getProperty("user.dir"), "src", "test", "resources").toString() + ); + identityTenantUtil = mockStatic(IdentityTenantUtil.class); + } + + @AfterMethod + public void tearDown() throws Exception { + + identityKeyStoreGenerator = null; + identityTenantUtil.close(); + } + + @Test(description = "Test the generation of a keystore for a given tenant domain and context if exits.") + public void testGenerateKeystoreIfExists() throws Exception { + + try (MockedStatic keyStoreManager = mockStatic(KeyStoreManager.class); + MockedStatic keyStoreUtils = mockStatic(KeystoreUtils.class)) { + + keyStoreManager.when(() -> KeyStoreManager.getInstance(anyInt())).thenReturn(this.keyStoreManager); + identityTenantUtil.when(()->IdentityTenantUtil.getTenantId("carbon.super")) + .thenReturn(-1234); + identityTenantUtil.when(() -> IdentityTenantUtil.initializeRegistry(anyInt())) + .thenAnswer((Answer) invocation -> null); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileLocation("carbon.super--cookie")) + .thenReturn("carbon-super--cookie.jks"); + when(this.keyStoreManager.getKeyStore("carbon-super--cookie.jks")) + .thenReturn(getKeyStoreFromFile("carbon-super--cookie.jks", KEYSTORE_PASSWORD)); + identityKeyStoreGenerator = new IdentityKeyStoreGeneratorImpl(); + identityKeyStoreGenerator.generateKeyStore("carbon.super", "cookie"); + } + } + + /** + * Sets up the mock behavior for KeyStoreManager and KeystoreUtils. + * + * @param exceptionToThrow the exception to throw when `getKeyStore` is called. + * @throws Exception if any setup steps fail. + */ + private void setupKeyStoreMocksWithException(Exception exceptionToThrow) throws Exception { + try (MockedStatic keyStoreManager = mockStatic(KeyStoreManager.class); + MockedStatic keyStoreUtils = mockStatic(KeystoreUtils.class)) { + + keyStoreManager.when(() -> KeyStoreManager.getInstance(anyInt())).thenReturn(this.keyStoreManager); + identityTenantUtil.when(() -> IdentityTenantUtil.getTenantId("carbon.super")).thenReturn(-1234); + identityTenantUtil.when(() -> IdentityTenantUtil.initializeRegistry(anyInt())) + .thenAnswer((Answer) invocation -> null); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileLocation("carbon.super--cookie")) + .thenReturn("wso2carbon--cookie.jks"); + + when(this.keyStoreManager.getKeyStore("wso2carbon--cookie.jks")).thenThrow(exceptionToThrow); + } + } + + @Test(description = "Test error creating a keystore for a given tenant domain and context with SecurityException.", + expectedExceptions = KeyStoreManagementException.class) + public void testGenerateKeystoreWithSecurityException() throws Exception { + + setupKeyStoreMocksWithException(new SecurityException("Error while creating keystore.")); + identityKeyStoreGenerator = new IdentityKeyStoreGeneratorImpl(); + identityKeyStoreGenerator.generateKeyStore("carbon.super", "cookie"); + } + + @Test(description = "Test error creating a keystore for a given tenant domain and context with generic Exception.", + expectedExceptions = KeyStoreManagementException.class) + public void testGenerateKeystoreWithGenericException() throws Exception { + + setupKeyStoreMocksWithException(new Exception("Error while creating keystore.")); + identityKeyStoreGenerator = new IdentityKeyStoreGeneratorImpl(); + identityKeyStoreGenerator.generateKeyStore("carbon.super", "cookie"); + } + + + @Test(description = "Test the generation of a keystore for a given tenant domain and context if not exits.") + public void testGenerateKeystoreIfNotExists() throws Exception { + + try (MockedStatic keyStoreManager = mockStatic(KeyStoreManager.class); + MockedStatic keyStoreUtils = mockStatic(KeystoreUtils.class)) { + + keyStoreManager.when(() -> KeyStoreManager.getInstance(anyInt())).thenReturn(this.keyStoreManager); + identityTenantUtil.when(()->IdentityTenantUtil.getTenantId("carbon.super")) + .thenReturn(-1234); + identityTenantUtil.when(() -> IdentityTenantUtil.initializeRegistry(anyInt())) + .thenAnswer((Answer) invocation -> null); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileLocation("carbon.super--cookie")) + .thenReturn("carbon-super--cookie.jks"); + when(this.keyStoreManager.getKeyStore("carbon-super--cookie.jks")) + .thenThrow(new SecurityException("Key Store with a name: carbon-super--cookie.jks" + + " does not exist.")); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileType("carbon.super")) + .thenReturn("JKS"); + keyStoreUtils.when(() -> KeystoreUtils.getKeystoreInstance("JKS")) + .thenReturn(this.mockKeyStore); + doNothing().when(this.mockKeyStore).setKeyEntry(anyString(), any(PrivateKey.class), any(), any()); + + identityKeyStoreGenerator = new IdentityKeyStoreGeneratorImpl(); + identityKeyStoreGenerator.generateKeyStore("carbon.super", "cookie"); + } + } + + @Test(description = "Test the generation of a keystore for a given tenant domain and context if not exits.") + public void testGenerateKeystoreAlreadyExists() throws Exception { + + try (MockedStatic keyStoreManager = mockStatic(KeyStoreManager.class); + MockedStatic keyStoreUtils = mockStatic(KeystoreUtils.class)) { + + keyStoreManager.when(() -> KeyStoreManager.getInstance(anyInt())).thenReturn(this.keyStoreManager); + identityTenantUtil.when(()->IdentityTenantUtil.getTenantId("carbon.super")) + .thenReturn(-1234); + identityTenantUtil.when(() -> IdentityTenantUtil.initializeRegistry(anyInt())) + .thenAnswer((Answer) invocation -> null); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileLocation("carbon.super--cookie")) + .thenReturn("carbon-super--cookie.jks"); + when(this.keyStoreManager.getKeyStore("carbon-super--cookie.jks")) + .thenThrow(new SecurityException("Key Store with a name: carbon-super--cookie.jks" + + " does not exist.")); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileType("carbon.super")) + .thenReturn("JKS"); + keyStoreUtils.when(() -> KeystoreUtils.getKeystoreInstance("JKS")) + .thenReturn(this.mockKeyStore); + doNothing().when(this.mockKeyStore).setKeyEntry(anyString(), any(PrivateKey.class), any(), any()); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension("carbon.super")) + .thenReturn(".jks"); + doThrow(new SecurityException("Key store carbon-super--cookie.jks already available")) + .when(this.keyStoreManager) + .addKeyStore( + any(byte[].class), // Match any byte array + anyString(), // Match any String + any(char[].class), // Match any char array + anyString(), // Match any String + anyString(), // Match any String + any(char[].class) // Match any char array + ); + + identityKeyStoreGenerator = new IdentityKeyStoreGeneratorImpl(); + identityKeyStoreGenerator.generateKeyStore("carbon.super", "cookie"); + } + } + + @Test(description = "Test the generation of a keystore for a given tenant domain and context if not exits.", + expectedExceptions = KeyStoreManagementException.class) + public void testGenerateKeystoreIfNotExistsNegative() throws Exception { + + try (MockedStatic keyStoreManager = mockStatic(KeyStoreManager.class); + MockedStatic keyStoreUtils = mockStatic(KeystoreUtils.class)) { + + keyStoreManager.when(() -> KeyStoreManager.getInstance(anyInt())).thenReturn(this.keyStoreManager); + identityTenantUtil.when(()->IdentityTenantUtil.getTenantId("carbon.super")) + .thenReturn(-1234); + identityTenantUtil.when(() -> IdentityTenantUtil.initializeRegistry(anyInt())) + .thenAnswer((Answer) invocation -> null); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileLocation("carbon.super--cookie")) + .thenReturn("carbon-super--cookie.jks"); + when(this.keyStoreManager.getKeyStore("carbon-super--cookie.jks")) + .thenThrow(new SecurityException("Key Store with a name: carbon-super--cookie.jks" + + " does not exist.")); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileType("carbon.super")) + .thenReturn("JKS"); + keyStoreUtils.when(() -> KeystoreUtils.getKeystoreInstance("JKS")) + .thenReturn(this.mockKeyStore); + doNothing().when(this.mockKeyStore).setKeyEntry(anyString(), any(PrivateKey.class), any(), any()); + keyStoreUtils.when(() -> KeystoreUtils.getKeyStoreFileExtension("carbon.super")) + .thenReturn(".jks"); + doThrow(new SecurityException("Error while adding keystore")) + .when(this.keyStoreManager) + .addKeyStore( + any(byte[].class), // Match any byte array + anyString(), // Match any String + any(char[].class), // Match any char array + anyString(), // Match any String + anyString(), // Match any String + any(char[].class) // Match any char array + ); + + identityKeyStoreGenerator = new IdentityKeyStoreGeneratorImpl(); + identityKeyStoreGenerator.generateKeyStore("carbon.super", "cookie"); + } + } + + + private Path createPath(String keystoreName) { + + return Paths.get(System.getProperty(CarbonBaseConstants.CARBON_HOME), "repository", + "resources", "security", keystoreName); + } + + private KeyStore getKeyStoreFromFile(String keystoreName, String password) throws Exception { + + Path tenantKeystorePath = createPath(keystoreName); + FileInputStream file = new FileInputStream(tenantKeystorePath.toString()); + KeyStore keystore = KeyStore.getInstance("JKS"); + keystore.load(file, password.toCharArray()); + return keystore; + } +} diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/repository/resources/security/carbon-super--cookie.jks b/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/repository/resources/security/carbon-super--cookie.jks new file mode 100644 index 000000000000..d5af4f42973a Binary files /dev/null and b/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/repository/resources/security/carbon-super--cookie.jks differ diff --git a/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/testng.xml b/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/testng.xml index ccc588beafc0..b74b69a95034 100644 --- a/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/testng.xml +++ b/components/security-mgt/org.wso2.carbon.security.mgt/src/test/resources/testng.xml @@ -23,6 +23,7 @@ + diff --git a/components/security-mgt/pom.xml b/components/security-mgt/pom.xml index 4b9c7e93fb14..bcf7b34f5f2c 100644 --- a/components/security-mgt/pom.xml +++ b/components/security-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/template-mgt/org.wso2.carbon.identity.template.mgt.ui/pom.xml b/components/template-mgt/org.wso2.carbon.identity.template.mgt.ui/pom.xml index 79323b936851..94853d7c9342 100644 --- a/components/template-mgt/org.wso2.carbon.identity.template.mgt.ui/pom.xml +++ b/components/template-mgt/org.wso2.carbon.identity.template.mgt.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework template-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/template-mgt/org.wso2.carbon.identity.template.mgt/pom.xml b/components/template-mgt/org.wso2.carbon.identity.template.mgt/pom.xml index 01bd843e7d76..e921243ca846 100644 --- a/components/template-mgt/org.wso2.carbon.identity.template.mgt/pom.xml +++ b/components/template-mgt/org.wso2.carbon.identity.template.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework template-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/components/template-mgt/pom.xml b/components/template-mgt/pom.xml index 5db50828f237..5b8d9327c162 100644 --- a/components/template-mgt/pom.xml +++ b/components/template-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt/pom.xml b/components/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt/pom.xml index 1c29d7ca53a5..af65a0dde2ec 100644 --- a/components/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt/pom.xml +++ b/components/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework trusted-app-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/trusted-app-mgt/pom.xml b/components/trusted-app-mgt/pom.xml index 797ad73c6718..f9c978f76358 100644 --- a/components/trusted-app-mgt/pom.xml +++ b/components/trusted-app-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt/pom.xml b/components/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt/pom.xml index 81ccfe1aa6c2..a1162b13d5bd 100644 --- a/components/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt/pom.xml +++ b/components/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt/pom.xml @@ -21,7 +21,7 @@ user-functionality-mgt org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT 4.0.0 diff --git a/components/user-functionality-mgt/pom.xml b/components/user-functionality-mgt/pom.xml index 635d85e71b8a..6266a43e7800 100644 --- a/components/user-functionality-mgt/pom.xml +++ b/components/user-functionality-mgt/pom.xml @@ -21,7 +21,7 @@ identity-framework org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.identity.user.profile.ui/pom.xml b/components/user-mgt/org.wso2.carbon.identity.user.profile.ui/pom.xml index d55370930dae..75b46777922d 100644 --- a/components/user-mgt/org.wso2.carbon.identity.user.profile.ui/pom.xml +++ b/components/user-mgt/org.wso2.carbon.identity.user.profile.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.identity.user.profile/pom.xml b/components/user-mgt/org.wso2.carbon.identity.user.profile/pom.xml index de53559ebe5f..96ce53d345df 100644 --- a/components/user-mgt/org.wso2.carbon.identity.user.profile/pom.xml +++ b/components/user-mgt/org.wso2.carbon.identity.user.profile/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.identity.user.registration/pom.xml b/components/user-mgt/org.wso2.carbon.identity.user.registration/pom.xml index 4a02fd94d07f..f954c955abe6 100644 --- a/components/user-mgt/org.wso2.carbon.identity.user.registration/pom.xml +++ b/components/user-mgt/org.wso2.carbon.identity.user.registration/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.role.mgt.ui/pom.xml b/components/user-mgt/org.wso2.carbon.role.mgt.ui/pom.xml index 46728560f968..91d63d2e5d1f 100644 --- a/components/user-mgt/org.wso2.carbon.role.mgt.ui/pom.xml +++ b/components/user-mgt/org.wso2.carbon.role.mgt.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.user.mgt.common/pom.xml b/components/user-mgt/org.wso2.carbon.user.mgt.common/pom.xml index 8620de64ef1d..4293ee704e1d 100644 --- a/components/user-mgt/org.wso2.carbon.user.mgt.common/pom.xml +++ b/components/user-mgt/org.wso2.carbon.user.mgt.common/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.user.mgt.ui/pom.xml b/components/user-mgt/org.wso2.carbon.user.mgt.ui/pom.xml index ea910ac4e1f8..c19092f3f519 100644 --- a/components/user-mgt/org.wso2.carbon.user.mgt.ui/pom.xml +++ b/components/user-mgt/org.wso2.carbon.user.mgt.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/org.wso2.carbon.user.mgt/pom.xml b/components/user-mgt/org.wso2.carbon.user.mgt/pom.xml index 0493908fbabb..6489a728f3fa 100644 --- a/components/user-mgt/org.wso2.carbon.user.mgt/pom.xml +++ b/components/user-mgt/org.wso2.carbon.user.mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-mgt/pom.xml b/components/user-mgt/pom.xml index dc6898c712b5..f0e18c5b9db4 100644 --- a/components/user-mgt/pom.xml +++ b/components/user-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/components/user-store/org.wso2.carbon.identity.user.store.configuration.deployer/pom.xml b/components/user-store/org.wso2.carbon.identity.user.store.configuration.deployer/pom.xml index c673daec3594..4814dedb87b6 100644 --- a/components/user-store/org.wso2.carbon.identity.user.store.configuration.deployer/pom.xml +++ b/components/user-store/org.wso2.carbon.identity.user.store.configuration.deployer/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-store - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-store/org.wso2.carbon.identity.user.store.configuration.ui/pom.xml b/components/user-store/org.wso2.carbon.identity.user.store.configuration.ui/pom.xml index 905507a249f0..3bd6cdb51e8c 100644 --- a/components/user-store/org.wso2.carbon.identity.user.store.configuration.ui/pom.xml +++ b/components/user-store/org.wso2.carbon.identity.user.store.configuration.ui/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-store - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-store/org.wso2.carbon.identity.user.store.configuration/pom.xml b/components/user-store/org.wso2.carbon.identity.user.store.configuration/pom.xml index 513c574f6a8a..761bf48c3ce9 100644 --- a/components/user-store/org.wso2.carbon.identity.user.store.configuration/pom.xml +++ b/components/user-store/org.wso2.carbon.identity.user.store.configuration/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-store - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-store/org.wso2.carbon.identity.user.store.count/pom.xml b/components/user-store/org.wso2.carbon.identity.user.store.count/pom.xml index 22a5c984b348..049e460ec2ca 100644 --- a/components/user-store/org.wso2.carbon.identity.user.store.count/pom.xml +++ b/components/user-store/org.wso2.carbon.identity.user.store.count/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-store - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/components/user-store/pom.xml b/components/user-store/pom.xml index c3889bf417f5..dfbd85720d4a 100644 --- a/components/user-store/pom.xml +++ b/components/user-store/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/action-mgt/org.wso2.carbon.identity.action.management.server.feature/pom.xml b/features/action-mgt/org.wso2.carbon.identity.action.management.server.feature/pom.xml index c0a08894fd20..5e9e54411756 100644 --- a/features/action-mgt/org.wso2.carbon.identity.action.management.server.feature/pom.xml +++ b/features/action-mgt/org.wso2.carbon.identity.action.management.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework action-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/action-mgt/pom.xml b/features/action-mgt/pom.xml index 1601d12180d4..465f1bd7b891 100644 --- a/features/action-mgt/pom.xml +++ b/features/action-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml index 68125e1fe19c..ba5c94f70794 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework api-resource-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml index 50971188b370..baf584c2765e 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml @@ -377,11 +377,9 @@ - - @@ -400,11 +398,9 @@ - - diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml.j2 b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml.j2 index 138b22fd1a1b..f80d74bc6106 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml.j2 +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/api-resource-collection.xml.j2 @@ -418,11 +418,9 @@ - - @@ -441,11 +439,9 @@ - - diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml index da31c426930a..f54bcb21ee44 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml @@ -665,8 +665,12 @@ + + + + + + + + + diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 index 9fba6a3582e6..8d2745f4c686 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 @@ -674,8 +674,12 @@ + + + + + + + + + diff --git a/features/api-resource-mgt/pom.xml b/features/api-resource-mgt/pom.xml index 770d4a1069b1..f68491b8c0fc 100644 --- a/features/api-resource-mgt/pom.xml +++ b/features/api-resource-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/application-mgt/org.wso2.carbon.identity.application.mgt.feature/pom.xml b/features/application-mgt/org.wso2.carbon.identity.application.mgt.feature/pom.xml index aee597c1048d..4e459aeceb9c 100644 --- a/features/application-mgt/org.wso2.carbon.identity.application.mgt.feature/pom.xml +++ b/features/application-mgt/org.wso2.carbon.identity.application.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework application-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/application-mgt/org.wso2.carbon.identity.application.mgt.server.feature/pom.xml b/features/application-mgt/org.wso2.carbon.identity.application.mgt.server.feature/pom.xml index 471ac096bc6a..83135ee9336e 100644 --- a/features/application-mgt/org.wso2.carbon.identity.application.mgt.server.feature/pom.xml +++ b/features/application-mgt/org.wso2.carbon.identity.application.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework application-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/application-mgt/org.wso2.carbon.identity.application.mgt.ui.feature/pom.xml b/features/application-mgt/org.wso2.carbon.identity.application.mgt.ui.feature/pom.xml index 0351d079eddb..23abe1af3cd2 100644 --- a/features/application-mgt/org.wso2.carbon.identity.application.mgt.ui.feature/pom.xml +++ b/features/application-mgt/org.wso2.carbon.identity.application.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework application-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/application-mgt/pom.xml b/features/application-mgt/pom.xml index 96b6c00cc5c6..ee905537579f 100644 --- a/features/application-mgt/pom.xml +++ b/features/application-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/pom.xml b/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/pom.xml index fa5b501f65db..83f094d7bb41 100644 --- a/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/pom.xml +++ b/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework authentication-framework-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json b/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json index 73bb267b475e..327624b7c9b8 100644 --- a/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json +++ b/features/authentication-framework/org.wso2.carbon.identity.application.authentication.framework.server.feature/resources/org.wso2.carbon.identity.application.authentication.framework.server.feature.default.json @@ -64,6 +64,7 @@ "authentication.authenticator.basic.parameters.AuthMechanism": "basic", "authentication.authenticator.basic.parameters.Tags": "Username-Password", "authentication.authenticator.basic.parameters.redirectToRetryPageOnAccountLock": "false", + "authentication.authenticator.basic.parameters.showAuthFailureReason": "true", "authentication.authenticator.basic_request_path.name": "BasicAuthRequestPathAuthenticator", "authentication.authenticator.basic_request_path.enable": true, diff --git a/features/authentication-framework/pom.xml b/features/authentication-framework/pom.xml index 249393ac5ca1..4af4239ebed0 100644 --- a/features/authentication-framework/pom.xml +++ b/features/authentication-framework/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/carbon-authenticators/pom.xml b/features/carbon-authenticators/pom.xml index 465600df8fdb..c4c0bfd6fc77 100644 --- a/features/carbon-authenticators/pom.xml +++ b/features/carbon-authenticators/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.thrift.authentication.feature/pom.xml b/features/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.thrift.authentication.feature/pom.xml index 56b212cc8bfd..70d9bcb7c7de 100644 --- a/features/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.thrift.authentication.feature/pom.xml +++ b/features/carbon-authenticators/thrift-authenticator/org.wso2.carbon.identity.thrift.authentication.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework thrift-authenticator-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/carbon-authenticators/thrift-authenticator/pom.xml b/features/carbon-authenticators/thrift-authenticator/pom.xml index 6e286a72a952..2ade41b2a8aa 100644 --- a/features/carbon-authenticators/thrift-authenticator/pom.xml +++ b/features/carbon-authenticators/thrift-authenticator/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-authenticator-features - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/categories/authorization/pom.xml b/features/categories/authorization/pom.xml index fc16536cba39..d873193f587b 100644 --- a/features/categories/authorization/pom.xml +++ b/features/categories/authorization/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/inbound-authentication/pom.xml b/features/categories/inbound-authentication/pom.xml index d311c4682911..4ffb0fce6a35 100644 --- a/features/categories/inbound-authentication/pom.xml +++ b/features/categories/inbound-authentication/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/inbound-provisioning/pom.xml b/features/categories/inbound-provisioning/pom.xml index 82eb8f0fc415..42168805648e 100644 --- a/features/categories/inbound-provisioning/pom.xml +++ b/features/categories/inbound-provisioning/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/keystore-mgt/pom.xml b/features/categories/keystore-mgt/pom.xml index 345411eb22ec..6a61431f4a1f 100644 --- a/features/categories/keystore-mgt/pom.xml +++ b/features/categories/keystore-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/notification-mgt/pom.xml b/features/categories/notification-mgt/pom.xml index fdf615b5bcd1..c8aee5b14c42 100644 --- a/features/categories/notification-mgt/pom.xml +++ b/features/categories/notification-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/outbound-authentication/pom.xml b/features/categories/outbound-authentication/pom.xml index ebbfe3d8f316..17a11e2f5998 100644 --- a/features/categories/outbound-authentication/pom.xml +++ b/features/categories/outbound-authentication/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/outbound-provisioning/pom.xml b/features/categories/outbound-provisioning/pom.xml index 633615621b11..9cd54abdd3d2 100644 --- a/features/categories/outbound-provisioning/pom.xml +++ b/features/categories/outbound-provisioning/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/categories/pom.xml b/features/categories/pom.xml index d35f54fe0a9b..712c7cbd4884 100644 --- a/features/categories/pom.xml +++ b/features/categories/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/categories/user-mgt/pom.xml b/features/categories/user-mgt/pom.xml index 74735294e9e7..cf3565e84464 100644 --- a/features/categories/user-mgt/pom.xml +++ b/features/categories/user-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../../pom.xml diff --git a/features/central-logger/org.wso2.carbon.identity.central.log.mgt.server.feature/pom.xml b/features/central-logger/org.wso2.carbon.identity.central.log.mgt.server.feature/pom.xml index 0d14c4297993..8f78614b4e65 100644 --- a/features/central-logger/org.wso2.carbon.identity.central.log.mgt.server.feature/pom.xml +++ b/features/central-logger/org.wso2.carbon.identity.central.log.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework central-logger-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/central-logger/pom.xml b/features/central-logger/pom.xml index c3e3a0a01a85..88101c55bf60 100644 --- a/features/central-logger/pom.xml +++ b/features/central-logger/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/certificate-mgt/org.wso2.carbon.identity.certificate.management.server.feature/pom.xml b/features/certificate-mgt/org.wso2.carbon.identity.certificate.management.server.feature/pom.xml index 2ea5cabaefee..8923100b7bc5 100644 --- a/features/certificate-mgt/org.wso2.carbon.identity.certificate.management.server.feature/pom.xml +++ b/features/certificate-mgt/org.wso2.carbon.identity.certificate.management.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework certificate-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/certificate-mgt/pom.xml b/features/certificate-mgt/pom.xml index 30e1dd8dfa41..09999d591785 100644 --- a/features/certificate-mgt/pom.xml +++ b/features/certificate-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/claim-mgt/org.wso2.carbon.claim.mgt.feature/pom.xml b/features/claim-mgt/org.wso2.carbon.claim.mgt.feature/pom.xml index a4a4bf894a20..1f8c24954cda 100644 --- a/features/claim-mgt/org.wso2.carbon.claim.mgt.feature/pom.xml +++ b/features/claim-mgt/org.wso2.carbon.claim.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework claim-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/pom.xml b/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/pom.xml index 64a44327acc9..178839b2a6f9 100644 --- a/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/pom.xml +++ b/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework claim-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/resources/conf/claim-config.xml b/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/resources/conf/claim-config.xml index e3c829346c9f..54dda2376dff 100644 --- a/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/resources/conf/claim-config.xml +++ b/features/claim-mgt/org.wso2.carbon.claim.mgt.server.feature/resources/conf/claim-config.xml @@ -844,6 +844,14 @@ true + + http://wso2.org/claims/identity/passwordExpiryTime + Password Expiry Time + passwordExpiryTime + Claim to dynamically calculate password expiry time of user + true + request + @@ -2727,6 +2735,13 @@ 14 http://wso2.org/claims/verifiedMobileNumbers + + urn:scim:wso2:schema:passwordExpiryTime + Password Expiry Time + passwordExpiryTime + Password Expiry Time + http://wso2.org/claims/identity/passwordExpiryTime + diff --git a/features/claim-mgt/org.wso2.carbon.claim.mgt.ui.feature/pom.xml b/features/claim-mgt/org.wso2.carbon.claim.mgt.ui.feature/pom.xml index 497d4d093392..75e348a7b6df 100644 --- a/features/claim-mgt/org.wso2.carbon.claim.mgt.ui.feature/pom.xml +++ b/features/claim-mgt/org.wso2.carbon.claim.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework claim-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/claim-mgt/pom.xml b/features/claim-mgt/pom.xml index ba565e9529be..c3f6068c0806 100644 --- a/features/claim-mgt/pom.xml +++ b/features/claim-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt.server.feature/pom.xml b/features/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt.server.feature/pom.xml index 1f55997d34de..c2ba26bbb2e9 100644 --- a/features/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt.server.feature/pom.xml +++ b/features/client-attestation-mgt/org.wso2.carbon.identity.client.attestation.mgt.server.feature/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework client-attestation-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/client-attestation-mgt/pom.xml b/features/client-attestation-mgt/pom.xml index b45dff5f75a5..8a1511585334 100644 --- a/features/client-attestation-mgt/pom.xml +++ b/features/client-attestation-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.server.feature/pom.xml b/features/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.server.feature/pom.xml index 1590be70a5fc..f378ae585331 100644 --- a/features/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.server.feature/pom.xml +++ b/features/configuration-mgt/org.wso2.carbon.identity.configuration.mgt.server.feature/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework configuration-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/configuration-mgt/pom.xml b/features/configuration-mgt/pom.xml index c23d471f5fc8..f4c80348b5dd 100644 --- a/features/configuration-mgt/pom.xml +++ b/features/configuration-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/consent-mgt/org.wso2.carbon.identity.consent.mgt.server.feature/pom.xml b/features/consent-mgt/org.wso2.carbon.identity.consent.mgt.server.feature/pom.xml index 454c435fad03..7d6cfee958a6 100644 --- a/features/consent-mgt/org.wso2.carbon.identity.consent.mgt.server.feature/pom.xml +++ b/features/consent-mgt/org.wso2.carbon.identity.consent.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-consent-mgt-aggregator - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/consent-mgt/pom.xml b/features/consent-mgt/pom.xml index 5481cc074a20..91314197f570 100644 --- a/features/consent-mgt/pom.xml +++ b/features/consent-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt.server.feature/pom.xml b/features/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt.server.feature/pom.xml index bede92a6dc44..72ca85ba8cd1 100644 --- a/features/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt.server.feature/pom.xml +++ b/features/consent-server-configs-mgt/org.wso2.carbon.identity.consent.server.configs.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework consent-server-configs-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/consent-server-configs-mgt/pom.xml b/features/consent-server-configs-mgt/pom.xml index c86b3b856041..fdbbe5c31a12 100644 --- a/features/consent-server-configs-mgt/pom.xml +++ b/features/consent-server-configs-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/cors-mgt/org.wso2.carbon.identity.cors.mgt.server.feature/pom.xml b/features/cors-mgt/org.wso2.carbon.identity.cors.mgt.server.feature/pom.xml index 47b77312aa5f..46f2f0a47f64 100644 --- a/features/cors-mgt/org.wso2.carbon.identity.cors.mgt.server.feature/pom.xml +++ b/features/cors-mgt/org.wso2.carbon.identity.cors.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework cors-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/cors-mgt/pom.xml b/features/cors-mgt/pom.xml index f74e313e6bca..124e2b73232d 100644 --- a/features/cors-mgt/pom.xml +++ b/features/cors-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.feature/pom.xml b/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.feature/pom.xml index d0061209dff8..32a3c65362d8 100644 --- a/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.feature/pom.xml +++ b/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework directory-server-manager-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.server.feature/pom.xml b/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.server.feature/pom.xml index 8b7b5e806234..83a10ce593f4 100644 --- a/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.server.feature/pom.xml +++ b/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework directory-server-manager-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.ui.feature/pom.xml b/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.ui.feature/pom.xml index eff6c84a233f..ee2dea1ca63a 100644 --- a/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.ui.feature/pom.xml +++ b/features/directory-server-manager/org.wso2.carbon.directory.service.mgr.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework directory-server-manager-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/directory-server-manager/pom.xml b/features/directory-server-manager/pom.xml index 29993ebbf520..41cb6feeaa17 100644 --- a/features/directory-server-manager/pom.xml +++ b/features/directory-server-manager/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/extension-mgt/org.wso2.carbon.identity.extension.mgt.feature/pom.xml b/features/extension-mgt/org.wso2.carbon.identity.extension.mgt.feature/pom.xml index 81ad043b9c71..00e7f9015d1b 100644 --- a/features/extension-mgt/org.wso2.carbon.identity.extension.mgt.feature/pom.xml +++ b/features/extension-mgt/org.wso2.carbon.identity.extension.mgt.feature/pom.xml @@ -19,7 +19,7 @@ extension-management-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT org.wso2.carbon.identity.extension.mgt.feature diff --git a/features/extension-mgt/pom.xml b/features/extension-mgt/pom.xml index 70ade2b71f36..82967157972b 100644 --- a/features/extension-mgt/pom.xml +++ b/features/extension-mgt/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.feature/pom.xml b/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.feature/pom.xml index 0b36c07236c5..3426df4af49b 100644 --- a/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.feature/pom.xml +++ b/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework functions-library-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.server.feature/pom.xml b/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.server.feature/pom.xml index fe8e79c3645e..d73a590dd360 100644 --- a/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.server.feature/pom.xml +++ b/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework functions-library-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui.feature/pom.xml b/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui.feature/pom.xml index 0217af037b2d..c578ba92df85 100644 --- a/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui.feature/pom.xml +++ b/features/functions-library-mgt/org.wso2.carbon.identity.functions.library.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework functions-library-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/functions-library-mgt/pom.xml b/features/functions-library-mgt/pom.xml index 6366980ed6bb..0a8015c3044f 100644 --- a/features/functions-library-mgt/pom.xml +++ b/features/functions-library-mgt/pom.xml @@ -28,7 +28,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/identity-core/org.wso2.carbon.identity.core.feature/pom.xml b/features/identity-core/org.wso2.carbon.identity.core.feature/pom.xml index 392fcf7d7347..91365ff3aa92 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.feature/pom.xml +++ b/features/identity-core/org.wso2.carbon.identity.core.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-core-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/pom.xml b/features/identity-core/org.wso2.carbon.identity.core.server.feature/pom.xml index 4e145ed3544e..685d66d09fa8 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/pom.xml +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-core-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql index d54358c91286..c50fcd814592 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql @@ -2079,6 +2079,9 @@ CREATE TABLE IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -2101,6 +2104,9 @@ CREATE TABLE IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -2125,6 +2131,9 @@ CREATE TABLE IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -2150,7 +2159,7 @@ CREATE TABLE IDN_ACTION ( PRIMARY KEY (UUID) ) / -CREATE TABLE IDN_ACTION_ENDPOINT ( +CREATE TABLE IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -2177,6 +2186,43 @@ REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL = (NEXTVAL FOR IDN_OAUTH2_TOKEN_CLAIMS_SEQ); END / +CREATE TABLE IDN_RULE ( + ID INTEGER NOT NULL, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE BOOLEAN DEFAULT TRUE, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +) +/ +CREATE SEQUENCE IDN_RULE_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE TRIGGER IDN_RULE_TRIG NO CASCADE BEFORE INSERT ON IDN_RULE_REFERENCES +REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL + BEGIN ATOMIC + SET (NEW.ID) = (NEXTVAL FOR IDN_RULE_SEQ); + END +/ +CREATE TABLE IDN_RULE_REFERENCES ( + ID INTEGER NOT NULL, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +) +/ +CREATE SEQUENCE IDN_RULE_REFERENCES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE TRIGGER IDN_RULE_REFERENCES_TRIG NO CASCADE BEFORE INSERT ON IDN_RULE_REFERENCES +REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL + BEGIN ATOMIC + SET (NEW.ID) = (NEXTVAL FOR IDN_RULE_REFERENCES_SEQ); + END +/ -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- @@ -2334,7 +2380,7 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); / -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID); / -- CERTIFICATE -- @@ -2343,10 +2389,15 @@ CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID) CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID) / ---SAML-- +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID) +/ +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID) +/ + +-- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); / CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); / CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); -/ diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql index 1630c726bf68..d676b9584a5a 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql @@ -1363,6 +1363,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -1378,6 +1381,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -1395,6 +1401,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -1411,7 +1420,7 @@ CREATE TABLE IF NOT EXISTS IDN_ACTION ( PRIMARY KEY (UUID) ); -CREATE TABLE IF NOT EXISTS IDN_ACTION_ENDPOINT ( +CREATE TABLE IF NOT EXISTS IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -1545,6 +1554,26 @@ CREATE TABLE IF NOT EXISTS IDN_XACML_POLICY_STATUS ( POLICY_VERSION INTEGER NOT NULL DEFAULT -1, TENANT_ID INTEGER NOT NULL, PRIMARY KEY (ID) + +CREATE TABLE IF NOT EXISTS IDN_RULE ( + ID INTEGER NOT NULL AUTO_INCREMENT, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE BOOLEAN DEFAULT TRUE, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +); + +CREATE TABLE IF NOT EXISTS IDN_RULE_REFERENCES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE ); -- --------------------------- INDEX CREATION ----------------------------- @@ -1654,12 +1683,16 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID); -- CERTIFICATE -- CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID); CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + -- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql index cea3e86b9b5a..5960b16a27ca 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql @@ -1510,6 +1510,9 @@ CREATE TABLE IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -1524,6 +1527,9 @@ CREATE TABLE IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -1540,6 +1546,9 @@ CREATE TABLE IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -1557,8 +1566,8 @@ CREATE TABLE IDN_ACTION ( PRIMARY KEY (UUID) ); -IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_ACTION_ENDPOINT]') AND TYPE in (N'U')) -CREATE TABLE IDN_ACTION_ENDPOINT ( +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_ACTION_PROPERTIES]') AND TYPE in (N'U')) +CREATE TABLE IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -1577,6 +1586,29 @@ CREATE TABLE IDN_OAUTH2_TOKEN_CLAIMS ( FOREIGN KEY (APP_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE ); +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_RULE]') AND TYPE IN (N'U')) +CREATE TABLE IDN_RULE ( + ID INTEGER IDENTITY, + UUID CHAR(36) NOT NULL, + CONTENT VARBINARY(MAX) NOT NULL, + IS_ACTIVE BIT DEFAULT 1, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_RULE_REFERENCES]') AND TYPE IN (N'U')) +CREATE TABLE IDN_RULE_REFERENCES ( + ID INTEGER IDENTITY, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +); + -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- CREATE INDEX IDX_TC ON IDN_OAUTH2_ACCESS_TOKEN(TIME_CREATED); @@ -1685,17 +1717,22 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID); -- CERTIFICATE -- CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID); CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + -- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); + GO -- Trigger IDN_CLAIM delete by dialect on IDN_CLAIM_DIALECT deletion -- diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql index 0a177ef56dc1..88fd07cbe1e6 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql @@ -1526,6 +1526,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -1539,6 +1542,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -1554,6 +1560,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -1570,7 +1579,7 @@ CREATE TABLE IF NOT EXISTS IDN_ACTION ( PRIMARY KEY (UUID) )ENGINE NDB; -CREATE TABLE IF NOT EXISTS IDN_ACTION_ENDPOINT ( +CREATE TABLE IF NOT EXISTS IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -1588,6 +1597,27 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_TOKEN_CLAIMS ( FOREIGN KEY (APP_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE )ENGINE NDB; +CREATE TABLE IF NOT EXISTS IDN_RULE ( + ID INTEGER AUTO_INCREMENT, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE BOOLEAN DEFAULT TRUE, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDN_RULE_REFERENCES ( + ID INTEGER AUTO_INCREMENT, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +)ENGINE NDB; + -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- CREATE INDEX IDX_TC @@ -1724,13 +1754,18 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID); -- CERTIFICATE -- CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID); CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + -- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql index cc5db207c302..1898fd776121 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql @@ -1394,6 +1394,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -1407,6 +1410,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -1422,6 +1428,9 @@ CREATE TABLE IF NOT EXISTS IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -1438,7 +1447,7 @@ CREATE TABLE IF NOT EXISTS IDN_ACTION ( PRIMARY KEY (UUID) )DEFAULT CHARACTER SET latin1 ENGINE INNODB; -CREATE TABLE IF NOT EXISTS IDN_ACTION_ENDPOINT ( +CREATE TABLE IF NOT EXISTS IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -1456,6 +1465,27 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_TOKEN_CLAIMS ( FOREIGN KEY (APP_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE )DEFAULT CHARACTER SET latin1 ENGINE INNODB; +CREATE TABLE IF NOT EXISTS IDN_RULE ( + ID INTEGER AUTO_INCREMENT, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE BOOLEAN DEFAULT TRUE, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +)DEFAULT CHARACTER SET latin1 ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_RULE_REFERENCES ( + ID INTEGER AUTO_INCREMENT, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +)DEFAULT CHARACTER SET latin1 ENGINE INNODB; + -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- CREATE INDEX IDX_TC ON IDN_OAUTH2_ACCESS_TOKEN(TIME_CREATED); @@ -1560,13 +1590,18 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID); -- CERTIFICATE -- CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID); CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); ---SAML-- +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + +-- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql index 489e4dcca39a..bc205d6f02c2 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql @@ -2136,6 +2136,9 @@ CREATE TABLE IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -2160,6 +2163,9 @@ CREATE TABLE IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -2186,6 +2192,9 @@ CREATE TABLE IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -2213,7 +2222,7 @@ CREATE TABLE IDN_ACTION ( PRIMARY KEY (UUID) ) / -CREATE TABLE IDN_ACTION_ENDPOINT ( +CREATE TABLE IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -2242,6 +2251,45 @@ CREATE OR REPLACE TRIGGER IDN_OAUTH2_TOKEN_CLAIMS_TRIG SELECT IDN_OAUTH2_TOKEN_CLAIMS_SEQ.nextval INTO :NEW.ID FROM dual; END; / +CREATE TABLE IDN_RULE ( + ID INTEGER, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE CHAR (1) DEFAULT '1', + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +) +/ +CREATE SEQUENCE IDN_RULE_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_RULE_TRIGGER + BEFORE INSERT ON IDN_RULE + REFERENCING NEW AS NEW FOR EACH ROW + BEGIN + SELECT IDN_RULE_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDN_RULE_REFERENCES ( + ID INTEGER, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +) +/ +CREATE SEQUENCE IDN_RULE_REFERENCES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_RULE_REFERENCES_TRIGGER + BEFORE INSERT ON IDN_RULE_REFERENCES + REFERENCING NEW AS NEW FOR EACH ROW + BEGIN + SELECT IDN_RULE_REFERENCES_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- @@ -2391,7 +2439,7 @@ CREATE INDEX IDX_CON_FILE_RES_ID ON IDN_CONFIG_FILE (RESOURCE_ID) -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID) / -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID) +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID) / -- CERTIFICATE -- @@ -2400,10 +2448,15 @@ CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID) CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID) / +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID) +/ +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID) +/ + -- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); / CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); / CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); -/ diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql index 7e49ca8045fc..278df7952da5 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql @@ -2069,6 +2069,9 @@ CREATE TABLE IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -2093,6 +2096,9 @@ CREATE TABLE IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -2119,6 +2125,9 @@ CREATE TABLE IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -2146,7 +2155,7 @@ CREATE TABLE IDN_ACTION ( PRIMARY KEY (UUID) ) / -CREATE TABLE IDN_ACTION_ENDPOINT ( +CREATE TABLE IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -2175,7 +2184,45 @@ CREATE OR REPLACE TRIGGER IDN_OAUTH2_TOKEN_CLAIMS_TRIG SELECT IDN_OAUTH2_TOKEN_CLAIMS_SEQ.nextval INTO :NEW.ID FROM dual; END; / - +CREATE TABLE IDN_RULE ( + ID INTEGER, + UUID CHAR(36) NOT NULL, + CONTENT BLOB NOT NULL, + IS_ACTIVE CHAR (1) DEFAULT '1', + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (UUID) +) +/ +CREATE SEQUENCE IDN_RULE_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_RULE_TRIGGER + BEFORE INSERT ON IDN_RULE + REFERENCING NEW AS NEW FOR EACH ROW + BEGIN + SELECT IDN_RULE_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDN_RULE_REFERENCES ( + ID INTEGER, + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +) +/ +CREATE SEQUENCE IDN_RULE_REFERENCES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_RULE_REFERENCES_TRIGGER + BEFORE INSERT ON IDN_RULE_REFERENCES + REFERENCING NEW AS NEW FOR EACH ROW + BEGIN + SELECT IDN_RULE_REFERENCES_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- CREATE INDEX IDX_TC ON IDN_OAUTH2_ACCESS_TOKEN(TIME_CREATED) @@ -2296,7 +2343,7 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME) -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID) / -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID) +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID) / -- CERTIFICATE -- @@ -2305,10 +2352,15 @@ CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID) CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID) / +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID) +/ +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID) +/ + -- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); / CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); / CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); -/ diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql index 24407b7b0a6c..7b51ab2cf7c6 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql @@ -1630,6 +1630,9 @@ CREATE TABLE IDN_NOTIFICATION_TYPE ( NAME VARCHAR(255) NOT NULL, CHANNEL VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), CONSTRAINT NOTIFICATION_TYPE_KEY_CONSTRAINT UNIQUE (TYPE_KEY, CHANNEL, TENANT_ID), CONSTRAINT NOTIFICATION_TYPE_NAME_CONSTRAINT UNIQUE (NAME, CHANNEL, TENANT_ID) @@ -1646,6 +1649,9 @@ CREATE TABLE IDN_NOTIFICATION_ORG_TEMPLATE ( CONTENT_TYPE VARCHAR(50), TYPE_ID INTEGER NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT ORG_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, TENANT_ID), @@ -1664,6 +1670,9 @@ CREATE TABLE IDN_NOTIFICATION_APP_TEMPLATE ( TYPE_ID INTEGER NOT NULL, APP_ID VARCHAR(255) NOT NULL, TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, PRIMARY KEY (ID), FOREIGN KEY (TYPE_ID) REFERENCES IDN_NOTIFICATION_TYPE(ID) ON DELETE CASCADE, CONSTRAINT APP_NOTIFICATION_TEMPLATE_KEY_CONSTRAINT UNIQUE (TEMPLATE_KEY, TYPE_ID, APP_ID, TENANT_ID), @@ -1681,8 +1690,8 @@ CREATE TABLE IF NOT EXISTS IDN_ACTION ( PRIMARY KEY (UUID) ); -DROP TABLE IF EXISTS IDN_ACTION_ENDPOINT; -CREATE TABLE IF NOT EXISTS IDN_ACTION_ENDPOINT ( +DROP TABLE IF EXISTS IDN_ACTION_PROPERTIES; +CREATE TABLE IF NOT EXISTS IDN_ACTION_PROPERTIES ( ACTION_UUID CHAR(36) NOT NULL, PROPERTY_NAME VARCHAR(100) NOT NULL, PROPERTY_VALUE VARCHAR(255) NOT NULL, @@ -1703,6 +1712,33 @@ CREATE TABLE IDN_OAUTH2_TOKEN_CLAIMS ( FOREIGN KEY (APP_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE ); +DROP TABLE IF EXISTS IDN_RULE; +DROP SEQUENCE IF EXISTS IDN_RULE_SEQ; +CREATE SEQUENCE IDN_RULE_SEQ; +CREATE TABLE IDN_RULE ( + ID INTEGER NOT NULL DEFAULT NEXTVAL('IDN_RULE_SEQ'), + UUID CHAR(36) NOT NULL, + CONTENT BYTEA NOT NULL, + IS_ACTIVE BOOLEAN DEFAULT TRUE, + TENANT_ID INTEGER NOT NULL, + VERSION VARCHAR(15) NOT NULL, + PRIMARY KEY (ID) + UNIQUE (UUID) +); + +DROP TABLE IF EXISTS IDN_RULE_REFERENCES; +DROP SEQUENCE IF EXISTS IDN_RULE_REFERENCES_SEQ; +CREATE SEQUENCE IDN_RULE_REFERENCES_SEQ; +CREATE TABLE IDN_RULE_REFERENCES ( + ID INTEGER NOT NULL DEFAULT NEXTVAL('IDN_RULE_REFERENCES_SEQ'), + RULE_ID INTEGER NOT NULL, + FIELD_NAME VARCHAR(100) NOT NULL, + FIELD_REFERENCE VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (RULE_ID) REFERENCES IDN_RULE(ID) ON DELETE CASCADE +); + -- --------------------------- INDEX CREATION ----------------------------- -- IDN_OAUTH2_ACCESS_TOKEN -- CREATE INDEX IDX_TC ON IDN_OAUTH2_ACCESS_TOKEN(TIME_CREATED); @@ -1813,12 +1849,16 @@ CREATE INDEX API_ID_NAME_INDEX ON SCOPE (API_ID, NAME); -- ACTIONS -- CREATE INDEX IDX_IDN_ACTION_TY_TI ON IDN_ACTION (TYPE, TENANT_ID); -CREATE INDEX IDX_IDN_ACTION_ENDPOINT_AU_TI ON IDN_ACTION_ENDPOINT (ACTION_UUID, TENANT_ID); +CREATE INDEX IDX_IDN_ACTION_PROPERTIES_AU_TI ON IDN_ACTION_PROPERTIES (ACTION_UUID, TENANT_ID); -- CERTIFICATE -- CREATE INDEX IDX_IDN_CERTIFICATE_ID_TID ON IDN_CERTIFICATE (ID, TENANT_ID); CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); +-- RULES -- +CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); +CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + -- SAML -- CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml index 6e0b2662e036..5e5159bfa1c3 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml @@ -78,7 +78,6 @@ database database - @@ -1174,6 +1173,7 @@ true + false @@ -1274,6 +1274,9 @@ identity data store value is empty for corresponding claim. --> false + @@ -2318,6 +2321,19 @@ internal_action_mgt_view + + /permission/admin/manage/custom_authenticator/create + internal_custom_authenticator_create + + + /permission/admin/manage/custom_authenticator/update + internal_custom_authenticator_update + + + /permission/admin/manage/custom_authenticator/delete + internal_custom_authenticator_delete + + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 index 3d6057494470..e586c1a6c036 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 @@ -86,7 +86,6 @@ --> {{data_storage_type.notification_templates}} - {{data_storage_type.keystores}} {{data_storage_type.xacml}} {{data_storage_type.saml}} @@ -97,6 +96,11 @@ {{tenant}} {% endfor %} + + {% for tenant in notification_templates.debug_tenants %} + {{tenant}} + {% endfor %} + {{notification_templates.sms_templates.apply}} @@ -962,6 +966,7 @@ {{oauth.oidc.extensions.user_info_claim_retriever}} {{oauth.oidc.extensions.user_info_request_validator}} {{oauth.oidc.extensions.user_info_access_token_validator}} + {{oauth.oidc.user_info.enable_multi_value_support}} {% if oauth.oidc.extensions.user_info_response_builder is defined %} {{oauth.oidc.extensions.user_info_response_builder}} {% else %} @@ -1909,6 +1914,7 @@ {{identity_mgt_account_suspension.use_identity_claims}} + {{identity_mgt_account_suspension.execute_task_on_master_node}} @@ -2048,6 +2054,13 @@ {{application_mgt.trusted_app_max_thumbprint_count}} + + + {% if role_mgt.allow_system_prefix_for_role is defined %} + {{role_mgt.allow_system_prefix_for_role}} + {% endif %} + + {% if outbound_provisioning_management.reset_provisioning_entities_on_config_update is defined %} {{event.default_listener.governance_identity_store.enable_hybrid_data_store}} + internal_action_mgt_view + + /permission/admin/manage/custom_authenticator/create + internal_custom_authenticator_create + + + /permission/admin/manage/custom_authenticator/update + internal_custom_authenticator_update + + + /permission/admin/manage/custom_authenticator/delete + internal_custom_authenticator_delete + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json index b7afb2dd8c83..199e02614d84 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json @@ -10,6 +10,7 @@ "identity.data_source": "jdbc/WSO2IdentityDB", "identity_data_source.skip_db_schema_creation": false, "identity_data_source.skip_claim_metadata_persistence": true, + "data_storage_type.notification_templates": "database", "database.identity_db.pool_options.maxActive": "50", "database.identity_db.pool_options.maxWait": "60000", "database.identity_db.pool_options.testOnBorrow": "true", @@ -250,6 +251,7 @@ "oauth.oidc.extensions.user_info_claim_retriever": "org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoUserStoreClaimRetriever", "oauth.oidc.extensions.user_info_request_validator": "org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInforRequestDefaultValidator", "oauth.oidc.extensions.user_info_access_token_validator": "org.wso2.carbon.identity.oauth.endpoint.user.impl.UserInfoISAccessTokenValidator", + "oauth.oidc.user_info.enable_multi_value_support": true, "oauth.oidc.request_object_builder.request_param_value_builder.enabled": true, "oauth.oidc.request_object_builder.request_param_value_builder.class": "org.wso2.carbon.identity.openidconnect.RequestParamRequestObjectBuilder", @@ -494,7 +496,7 @@ "identity_mgt.user_claim_update.uniqueness.enable": false, "identity_mgt.user_claim_update.uniqueness.listener_priority": "2", "identity_mgt.user_claim_update.uniqueness.scope_within_userstore": false, - "identity_mgt.user_claim_update.enable_multiple_emails_and_mobile_numbers": false, + "identity_mgt.user_claim_update.enable_multiple_emails_and_mobile_numbers": true, "event.default_listener.system_api_resource_management_listener.priority": "211", "event.default_listener.system_api_resource_management_listener.enable": true, @@ -503,6 +505,7 @@ "event.default_listener.system_api_authorization_management_listener.enable": true, "identity_mgt_account_suspension.use_identity_claims": true, + "identity_mgt_account_suspension.execute_task_on_master_node": false, "identity_mgt.enable_user_claim_input_regex_validation": true, @@ -550,6 +553,8 @@ "event.default_listener.governance_identity_store.enable": true, "event.default_listener.governance_identity_store.data_store": "org.wso2.carbon.identity.governance.store.JDBCIdentityDataStore", "event.default_listener.governance_identity_store.enable_hybrid_data_store": false, + "event.default_listener.password_expiry.priority": "102", + "event.default_listener.password_expiry.enable": true, "event.default_listener.application_authentication.priority": "11", "event.default_listener.application_authentication.enable": true, "event.default_listener.mutual_tls_authenticator.priority": "919", diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml index 92659d558bfc..597d718ac883 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml @@ -326,6 +326,9 @@ /permission/admin/manage/identity/rolemgt/view internal_org_role_mgt_view + + internal_org_role_mgt_create + /permission/admin/manage/identity/rolemgt/update internal_org_role_mgt_update @@ -334,6 +337,9 @@ /permission/admin/manage/identity/rolemgt/update internal_org_role_mgt_update + + internal_org_role_mgt_delete + @@ -1207,6 +1213,17 @@ internal_rule_metadata_view + + + internal_custom_authenticator_create + + + internal_custom_authenticator_update + + + internal_custom_authenticator_delete + + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml.j2 b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml.j2 index cb0764b2f945..7c16366ce52b 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml.j2 +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/resource-access-control-v2.xml.j2 @@ -350,6 +350,9 @@ /permission/admin/manage/identity/rolemgt/view internal_org_role_mgt_view + + internal_org_role_mgt_create + /permission/admin/manage/identity/rolemgt/update internal_org_role_mgt_update @@ -358,6 +361,9 @@ /permission/admin/manage/identity/rolemgt/update internal_org_role_mgt_update + + internal_org_role_mgt_delete + @@ -1271,6 +1277,17 @@ internal_rule_metadata_view + + + internal_custom_authenticator_create + + + internal_custom_authenticator_update + + + internal_custom_authenticator_delete + + diff --git a/features/identity-core/org.wso2.carbon.identity.core.ui.feature/pom.xml b/features/identity-core/org.wso2.carbon.identity.core.ui.feature/pom.xml index 0ce1be0ff1af..32b4788419b8 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.ui.feature/pom.xml +++ b/features/identity-core/org.wso2.carbon.identity.core.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-core-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-core/pom.xml b/features/identity-core/pom.xml index eff2d12c66f4..fa86ae95ffee 100644 --- a/features/identity-core/pom.xml +++ b/features/identity-core/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/identity-event/org.wso2.carbon.identity.event.feature/pom.xml b/features/identity-event/org.wso2.carbon.identity.event.feature/pom.xml index d8b0624085ad..4b8cddf1cb67 100644 --- a/features/identity-event/org.wso2.carbon.identity.event.feature/pom.xml +++ b/features/identity-event/org.wso2.carbon.identity.event.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-event-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-event/org.wso2.carbon.identity.event.server.feature/pom.xml b/features/identity-event/org.wso2.carbon.identity.event.server.feature/pom.xml index 420ce5ee091e..2799c506e6b6 100644 --- a/features/identity-event/org.wso2.carbon.identity.event.server.feature/pom.xml +++ b/features/identity-event/org.wso2.carbon.identity.event.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-event-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-event/pom.xml b/features/identity-event/pom.xml index c995d5d11cc2..ec4699aa6907 100644 --- a/features/identity-event/pom.xml +++ b/features/identity-event/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/identity-mgt/org.wso2.carbon.identity.mgt.feature/pom.xml b/features/identity-mgt/org.wso2.carbon.identity.mgt.feature/pom.xml index 067d668b50be..030cd3e0698e 100644 --- a/features/identity-mgt/org.wso2.carbon.identity.mgt.feature/pom.xml +++ b/features/identity-mgt/org.wso2.carbon.identity.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-mgt/org.wso2.carbon.identity.mgt.server.feature/pom.xml b/features/identity-mgt/org.wso2.carbon.identity.mgt.server.feature/pom.xml index 532a7dee362c..bb5922c5a299 100644 --- a/features/identity-mgt/org.wso2.carbon.identity.mgt.server.feature/pom.xml +++ b/features/identity-mgt/org.wso2.carbon.identity.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-mgt/org.wso2.carbon.identity.mgt.ui.feature/pom.xml b/features/identity-mgt/org.wso2.carbon.identity.mgt.ui.feature/pom.xml index eb8f73efde15..e4b597a659a7 100644 --- a/features/identity-mgt/org.wso2.carbon.identity.mgt.ui.feature/pom.xml +++ b/features/identity-mgt/org.wso2.carbon.identity.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/identity-mgt/pom.xml b/features/identity-mgt/pom.xml index 976b3baa4cdc..bfcae29cb873 100644 --- a/features/identity-mgt/pom.xml +++ b/features/identity-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/idp-mgt/org.wso2.carbon.idp.mgt.feature/pom.xml b/features/idp-mgt/org.wso2.carbon.idp.mgt.feature/pom.xml index c7c7ff1d2fb9..11bd4b4fa4bf 100644 --- a/features/idp-mgt/org.wso2.carbon.idp.mgt.feature/pom.xml +++ b/features/idp-mgt/org.wso2.carbon.idp.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-provider-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/idp-mgt/org.wso2.carbon.idp.mgt.server.feature/pom.xml b/features/idp-mgt/org.wso2.carbon.idp.mgt.server.feature/pom.xml index 5b34bb2cad58..3f5598e06d58 100644 --- a/features/idp-mgt/org.wso2.carbon.idp.mgt.server.feature/pom.xml +++ b/features/idp-mgt/org.wso2.carbon.idp.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-provider-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/idp-mgt/org.wso2.carbon.idp.mgt.ui.feature/pom.xml b/features/idp-mgt/org.wso2.carbon.idp.mgt.ui.feature/pom.xml index a96554f120fd..a2ecc061a5e7 100644 --- a/features/idp-mgt/org.wso2.carbon.idp.mgt.ui.feature/pom.xml +++ b/features/idp-mgt/org.wso2.carbon.idp.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-provider-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/idp-mgt/pom.xml b/features/idp-mgt/pom.xml index 9849925e57e1..70bb80f4993c 100644 --- a/features/idp-mgt/pom.xml +++ b/features/idp-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt.server.feature/pom.xml b/features/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt.server.feature/pom.xml index a6563189c760..b2284b3af1f2 100644 --- a/features/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt.server.feature/pom.xml +++ b/features/input-validation-mgt/org.wso2.carbon.identity.input.validation.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework input-validation-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/input-validation-mgt/pom.xml b/features/input-validation-mgt/pom.xml index 03b83a59f196..437341286f6a 100644 --- a/features/input-validation-mgt/pom.xml +++ b/features/input-validation-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt.server.feature/pom.xml b/features/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt.server.feature/pom.xml index e60da77e5e8a..d6450780696b 100644 --- a/features/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt.server.feature/pom.xml +++ b/features/multi-attribute-login/org.wso2.carbon.identity.multi.attribute.login.mgt.server.feature/pom.xml @@ -20,7 +20,7 @@ multi-attribute-login-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt.server.feature/pom.xml b/features/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt.server.feature/pom.xml index 29bed36db307..c71e22a3d809 100644 --- a/features/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt.server.feature/pom.xml +++ b/features/multi-attribute-login/org.wso2.carbon.identity.unique.claim.mgt.server.feature/pom.xml @@ -20,7 +20,7 @@ multi-attribute-login-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/multi-attribute-login/pom.xml b/features/multi-attribute-login/pom.xml index b644bec2addc..65f7263adb13 100644 --- a/features/multi-attribute-login/pom.xml +++ b/features/multi-attribute-login/pom.xml @@ -20,7 +20,7 @@ identity-framework org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.feature/pom.xml b/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.feature/pom.xml index 509d45fcb4c0..571d00112343 100644 --- a/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.feature/pom.xml +++ b/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-notification-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.server.feature/pom.xml b/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.server.feature/pom.xml index f7d65373a500..93c80427fdbd 100644 --- a/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.server.feature/pom.xml +++ b/features/notification-mgt/org.wso2.carbon.identity.notification.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-notification-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/notification-mgt/pom.xml b/features/notification-mgt/pom.xml index 0756ddca8f2c..6fe03eb1b094 100644 --- a/features/notification-mgt/pom.xml +++ b/features/notification-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/provisioning/org.wso2.carbon.identity.provisioning.server.feature/pom.xml b/features/provisioning/org.wso2.carbon.identity.provisioning.server.feature/pom.xml index ae125c9a0a02..94aa1409e5f9 100644 --- a/features/provisioning/org.wso2.carbon.identity.provisioning.server.feature/pom.xml +++ b/features/provisioning/org.wso2.carbon.identity.provisioning.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework provisioning-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/provisioning/pom.xml b/features/provisioning/pom.xml index cfaf924e526a..85cc6c3874f8 100644 --- a/features/provisioning/pom.xml +++ b/features/provisioning/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/role-mgt/org.wso2.carbon.identity.role.mgt.core.server.feature/pom.xml b/features/role-mgt/org.wso2.carbon.identity.role.mgt.core.server.feature/pom.xml index 27d45e5385ac..e0418a48780c 100644 --- a/features/role-mgt/org.wso2.carbon.identity.role.mgt.core.server.feature/pom.xml +++ b/features/role-mgt/org.wso2.carbon.identity.role.mgt.core.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework role-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core.server.feature/pom.xml b/features/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core.server.feature/pom.xml index af9b13cab2b1..d5bcea0a7eba 100644 --- a/features/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core.server.feature/pom.xml +++ b/features/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core.server.feature/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework role-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/role-mgt/pom.xml b/features/role-mgt/pom.xml index 32bfca83e2dd..6b5ef036dbd8 100644 --- a/features/role-mgt/pom.xml +++ b/features/role-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/pom.xml b/features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/pom.xml index 974d688e1cf1..a96dab522e0e 100644 --- a/features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/pom.xml +++ b/features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework rule-management-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/rule-mgt/pom.xml b/features/rule-mgt/pom.xml index e2195ed97bcc..7e9fccfebe27 100644 --- a/features/rule-mgt/pom.xml +++ b/features/rule-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/secret-mgt/org.wso2.carbon.identity.secret.mgt.core.server.feature/pom.xml b/features/secret-mgt/org.wso2.carbon.identity.secret.mgt.core.server.feature/pom.xml index 9a506693bc5c..3ff64cfc49f6 100644 --- a/features/secret-mgt/org.wso2.carbon.identity.secret.mgt.core.server.feature/pom.xml +++ b/features/secret-mgt/org.wso2.carbon.identity.secret.mgt.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework secret-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT 4.0.0 diff --git a/features/secret-mgt/pom.xml b/features/secret-mgt/pom.xml index 86596dd72c27..4bab5285d458 100644 --- a/features/secret-mgt/pom.xml +++ b/features/secret-mgt/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/security-mgt/org.wso2.carbon.security.mgt.feature/pom.xml b/features/security-mgt/org.wso2.carbon.security.mgt.feature/pom.xml index 071d099b88c7..b02e90ccc0a3 100644 --- a/features/security-mgt/org.wso2.carbon.security.mgt.feature/pom.xml +++ b/features/security-mgt/org.wso2.carbon.security.mgt.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework security-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/security-mgt/org.wso2.carbon.security.mgt.server.feature/pom.xml b/features/security-mgt/org.wso2.carbon.security.mgt.server.feature/pom.xml index 424d34389998..7516bb1bf999 100644 --- a/features/security-mgt/org.wso2.carbon.security.mgt.server.feature/pom.xml +++ b/features/security-mgt/org.wso2.carbon.security.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework security-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/security-mgt/org.wso2.carbon.security.mgt.ui.feature/pom.xml b/features/security-mgt/org.wso2.carbon.security.mgt.ui.feature/pom.xml index e63ab325efb2..913538db356c 100644 --- a/features/security-mgt/org.wso2.carbon.security.mgt.ui.feature/pom.xml +++ b/features/security-mgt/org.wso2.carbon.security.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework security-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/security-mgt/pom.xml b/features/security-mgt/pom.xml index bdf0e8b32142..dd75f90514c3 100644 --- a/features/security-mgt/pom.xml +++ b/features/security-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/template-mgt/org.wso2.carbon.identity.template.mgt.feature/pom.xml b/features/template-mgt/org.wso2.carbon.identity.template.mgt.feature/pom.xml index 4fdddaab54db..de0c2be900bc 100644 --- a/features/template-mgt/org.wso2.carbon.identity.template.mgt.feature/pom.xml +++ b/features/template-mgt/org.wso2.carbon.identity.template.mgt.feature/pom.xml @@ -21,7 +21,7 @@ template-management-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/template-mgt/org.wso2.carbon.identity.template.mgt.server.feature/pom.xml b/features/template-mgt/org.wso2.carbon.identity.template.mgt.server.feature/pom.xml index b1f17b58ad67..1bb0d9e51754 100644 --- a/features/template-mgt/org.wso2.carbon.identity.template.mgt.server.feature/pom.xml +++ b/features/template-mgt/org.wso2.carbon.identity.template.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ template-management-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/template-mgt/org.wso2.carbon.identity.template.mgt.ui.feature/pom.xml b/features/template-mgt/org.wso2.carbon.identity.template.mgt.ui.feature/pom.xml index f54b851ab982..94cab1e7215e 100644 --- a/features/template-mgt/org.wso2.carbon.identity.template.mgt.ui.feature/pom.xml +++ b/features/template-mgt/org.wso2.carbon.identity.template.mgt.ui.feature/pom.xml @@ -21,7 +21,7 @@ template-management-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/template-mgt/pom.xml b/features/template-mgt/pom.xml index eeb93a86ce72..338486da6ede 100644 --- a/features/template-mgt/pom.xml +++ b/features/template-mgt/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt.server.feature/pom.xml b/features/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt.server.feature/pom.xml index d16fe0ef4a1e..c9c8894b9133 100644 --- a/features/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt.server.feature/pom.xml +++ b/features/trusted-app-mgt/org.wso2.carbon.identity.trusted.app.mgt.server.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework trusted-app-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/trusted-app-mgt/pom.xml b/features/trusted-app-mgt/pom.xml index d478eac2f01b..971065ce976d 100644 --- a/features/trusted-app-mgt/pom.xml +++ b/features/trusted-app-mgt/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.feature/pom.xml b/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.feature/pom.xml index 14a1bdc4ef5f..d9d24bcc0d2a 100644 --- a/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.feature/pom.xml +++ b/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.feature/pom.xml @@ -21,7 +21,7 @@ user-functionality-mgt-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.server.feature/pom.xml b/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.server.feature/pom.xml index d1bcde000fb0..fe15a1418397 100644 --- a/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.server.feature/pom.xml +++ b/features/user-functionality-mgt/org.wso2.carbon.identity.user.functionality.mgt.server.feature/pom.xml @@ -21,7 +21,7 @@ user-functionality-mgt-feature org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT 4.0.0 diff --git a/features/user-functionality-mgt/pom.xml b/features/user-functionality-mgt/pom.xml index 3757c0931069..ce8723e7dc4e 100644 --- a/features/user-functionality-mgt/pom.xml +++ b/features/user-functionality-mgt/pom.xml @@ -21,7 +21,7 @@ identity-framework org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/features/user-mgt/org.wso2.carbon.identity.user.profile.feature/pom.xml b/features/user-mgt/org.wso2.carbon.identity.user.profile.feature/pom.xml index 4f77bd5ac33c..320727888446 100644 --- a/features/user-mgt/org.wso2.carbon.identity.user.profile.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.identity.user.profile.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.identity.user.profile.server.feature/pom.xml b/features/user-mgt/org.wso2.carbon.identity.user.profile.server.feature/pom.xml index e9f05a793d40..044cfa39b249 100644 --- a/features/user-mgt/org.wso2.carbon.identity.user.profile.server.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.identity.user.profile.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.identity.user.profile.ui.feature/pom.xml b/features/user-mgt/org.wso2.carbon.identity.user.profile.ui.feature/pom.xml index 406f2002500b..a156f5b50ade 100644 --- a/features/user-mgt/org.wso2.carbon.identity.user.profile.ui.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.identity.user.profile.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.identity.user.registration.feature/pom.xml b/features/user-mgt/org.wso2.carbon.identity.user.registration.feature/pom.xml index 6efba3d056f4..c6752afb03d7 100644 --- a/features/user-mgt/org.wso2.carbon.identity.user.registration.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.identity.user.registration.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.identity.user.registration.server.feature/pom.xml b/features/user-mgt/org.wso2.carbon.identity.user.registration.server.feature/pom.xml index 2f4e026edb4f..9caac24b27cd 100644 --- a/features/user-mgt/org.wso2.carbon.identity.user.registration.server.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.identity.user.registration.server.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.identity.user.registration.ui.feature/pom.xml b/features/user-mgt/org.wso2.carbon.identity.user.registration.ui.feature/pom.xml index d289ae39b472..3a7b00abc094 100644 --- a/features/user-mgt/org.wso2.carbon.identity.user.registration.ui.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.identity.user.registration.ui.feature/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.role.mgt.ui.feature/pom.xml b/features/user-mgt/org.wso2.carbon.role.mgt.ui.feature/pom.xml index 3e5f2c7e4cbe..444c36f861c8 100644 --- a/features/user-mgt/org.wso2.carbon.role.mgt.ui.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.role.mgt.ui.feature/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.user.mgt.feature/pom.xml b/features/user-mgt/org.wso2.carbon.user.mgt.feature/pom.xml index 5f3cf374e293..94279440bc29 100644 --- a/features/user-mgt/org.wso2.carbon.user.mgt.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.user.mgt.feature/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.user.mgt.server.feature/pom.xml b/features/user-mgt/org.wso2.carbon.user.mgt.server.feature/pom.xml index 0e51ed55be25..1453eb42f2b5 100644 --- a/features/user-mgt/org.wso2.carbon.user.mgt.server.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.user.mgt.server.feature/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/org.wso2.carbon.user.mgt.ui.feature/pom.xml b/features/user-mgt/org.wso2.carbon.user.mgt.ui.feature/pom.xml index 2452ea476f23..2f553a0db705 100644 --- a/features/user-mgt/org.wso2.carbon.user.mgt.ui.feature/pom.xml +++ b/features/user-mgt/org.wso2.carbon.user.mgt.ui.feature/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.framework user-mgt-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-mgt/pom.xml b/features/user-mgt/pom.xml index 2d5cc20926f8..a55f546efef0 100644 --- a/features/user-mgt/pom.xml +++ b/features/user-mgt/pom.xml @@ -17,7 +17,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/features/user-store/org.wso2.carbon.identity.user.store.configuration.server.feature/pom.xml b/features/user-store/org.wso2.carbon.identity.user.store.configuration.server.feature/pom.xml index 991a768ceaea..857b23601831 100644 --- a/features/user-store/org.wso2.carbon.identity.user.store.configuration.server.feature/pom.xml +++ b/features/user-store/org.wso2.carbon.identity.user.store.configuration.server.feature/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework user-store-feature - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/features/user-store/pom.xml b/features/user-store/pom.xml index c2be9f5c7cde..fca007486dd4 100644 --- a/features/user-store/pom.xml +++ b/features/user-store/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/pom.xml b/pom.xml index 7dc6a2050855..4f40dc75894b 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.identity.framework identity-framework pom - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT WSO2 Carbon - Platform Aggregator Pom http://wso2.org @@ -335,6 +335,11 @@ org.wso2.carbon.identity.rule.metadata ${project.version} + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.rule.management + ${project.version} + org.wso2.carbon.identity.framework @@ -922,6 +927,17 @@ ${version.javax.servlet} + + org.wso2.orbit.org.bouncycastle + bcprov-jdk18on + ${bcprov-jdk18.version} + + + org.wso2.orbit.org.bouncycastle + bcpkix-jdk18on + ${bcpkix-jdk18.version} + + org.opensaml @@ -1832,7 +1848,7 @@ 4.7.39 [4.7.2, 5.0.0) - 2.1.7 + 2.2.2 [2.0.0,3.0.0) @@ -1840,6 +1856,7 @@ ${project.version} [5.14.0, 8.0.0) + [0.0.0,2.0.0) 1.0.90 [1.0.0, 2.0.0) @@ -1950,6 +1967,9 @@ 1.4.1 [1.4.0,1.5.0) + 1.78.1.wso2v1 + 1.78.1.wso2v1 + 1.8.0 3.2.2.wso2v1 diff --git a/service-stubs/identity/org.wso2.carbon.claim.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.claim.mgt.stub/pom.xml index 8b07ba2f6564..8e23c8573b22 100644 --- a/service-stubs/identity/org.wso2.carbon.claim.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.claim.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.directory.server.manager.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.directory.server.manager.stub/pom.xml index 7459f9ae05de..42cb60ba051d 100644 --- a/service-stubs/identity/org.wso2.carbon.directory.server.manager.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.directory.server.manager.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.application.authentication.framework.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.application.authentication.framework.stub/pom.xml index c3416bc7d451..fc523dfc596a 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.application.authentication.framework.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.application.authentication.framework.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml 4.0.0 diff --git a/service-stubs/identity/org.wso2.carbon.identity.application.default.authentication.sequence.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.application.default.authentication.sequence.mgt.stub/pom.xml index 35ceefbbea14..05451f8d2df3 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.application.default.authentication.sequence.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.application.default.authentication.sequence.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.application.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.application.mgt.stub/pom.xml index efa6c1334699..2369fc8b1167 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.application.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.application.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.claim.metadata.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.claim.metadata.mgt.stub/pom.xml index 097f5c7985fc..d51e35f42d91 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.claim.metadata.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.claim.metadata.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.functions.library.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.functions.library.mgt.stub/pom.xml index 83d8ba07d69c..52e4fb7f6232 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.functions.library.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.functions.library.mgt.stub/pom.xml @@ -21,7 +21,7 @@ carbon-service-stubs org.wso2.carbon.identity.framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT 4.0.0 diff --git a/service-stubs/identity/org.wso2.carbon.identity.governance.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.governance.stub/pom.xml index 5e5376516273..c350609c4e49 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.governance.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.governance.stub/pom.xml @@ -18,7 +18,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.mgt.stub/pom.xml index f3f119167f26..802b848dd42d 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.user.profile.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.user.profile.stub/pom.xml index aa196705fa1e..05326863528b 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.user.profile.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.user.profile.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.user.registration.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.user.registration.stub/pom.xml index 8eaf0933a6a6..bb2c82a23683 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.user.registration.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.user.registration.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.user.store.configuration.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.user.store.configuration.stub/pom.xml index 997ee3c4bdda..6b1ba4db31d7 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.user.store.configuration.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.user.store.configuration.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.identity.user.store.count.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.identity.user.store.count.stub/pom.xml index 6f8f10eeeb85..013de4241d43 100644 --- a/service-stubs/identity/org.wso2.carbon.identity.user.store.count.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.identity.user.store.count.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/pom.xml index 36e6a2f4cec6..6dbf1ab8e855 100644 --- a/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.security.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.security.mgt.stub/pom.xml index 6737da0c4b9a..5b53288d0c24 100644 --- a/service-stubs/identity/org.wso2.carbon.security.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.security.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/org.wso2.carbon.user.mgt.stub/pom.xml b/service-stubs/identity/org.wso2.carbon.user.mgt.stub/pom.xml index 47dec62a35cf..c9715a064645 100644 --- a/service-stubs/identity/org.wso2.carbon.user.mgt.stub/pom.xml +++ b/service-stubs/identity/org.wso2.carbon.user.mgt.stub/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework carbon-service-stubs - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../pom.xml diff --git a/service-stubs/identity/pom.xml b/service-stubs/identity/pom.xml index 33a701c18436..7117e0e7c919 100644 --- a/service-stubs/identity/pom.xml +++ b/service-stubs/identity/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml diff --git a/test-utils/org.wso2.carbon.identity.testutil/pom.xml b/test-utils/org.wso2.carbon.identity.testutil/pom.xml index 7e80a97443c7..e028ed0da4e8 100644 --- a/test-utils/org.wso2.carbon.identity.testutil/pom.xml +++ b/test-utils/org.wso2.carbon.identity.testutil/pom.xml @@ -18,7 +18,7 @@ org.wso2.carbon.identity.framework identity-framework - 7.7.28-SNAPSHOT + 7.7.51-SNAPSHOT ../../pom.xml