From 1eb590d31782170aedf65b6ef61844d5d7b44324 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Tue, 2 Jul 2024 04:56:02 +0000 Subject: [PATCH 01/11] [WSO2 Release] [Jenkins #209] [Release 1.1.9] prepare release v1.1.9 --- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/pom.xml b/components/org.wso2.carbon.identity.organization.management.service/pom.xml index 984cab6a..46a8ea18 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.service/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.9-SNAPSHOT + 1.1.9 ../../pom.xml diff --git a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml index cdd4ca3d..ab89e754 100644 --- a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.9-SNAPSHOT + 1.1.9 ../../pom.xml diff --git a/pom.xml b/pom.xml index 6ade7320..ed644a62 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.9-SNAPSHOT + 1.1.9 4.0.0 pom WSO2 Carbon - Organization Management Core @@ -36,7 +36,7 @@ https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git - HEAD + v1.1.9 From 79b5eae52410c4e218949fb60a8e25a8f5d21358 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Tue, 2 Jul 2024 04:56:04 +0000 Subject: [PATCH 02/11] [WSO2 Release] [Jenkins #209] [Release 1.1.9] prepare for next development iteration --- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/pom.xml b/components/org.wso2.carbon.identity.organization.management.service/pom.xml index 46a8ea18..70826ef6 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.service/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.9 + 1.1.10-SNAPSHOT ../../pom.xml diff --git a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml index ab89e754..3bf7c940 100644 --- a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.9 + 1.1.10-SNAPSHOT ../../pom.xml diff --git a/pom.xml b/pom.xml index ed644a62..8123a55a 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.9 + 1.1.10-SNAPSHOT 4.0.0 pom WSO2 Carbon - Organization Management Core @@ -36,7 +36,7 @@ https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git - v1.1.9 + HEAD From ec068e8daaf7fcf1173444cc4a13a90aafc4123b Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Fri, 5 Jul 2024 08:24:04 +0000 Subject: [PATCH 03/11] [WSO2 Release] [Jenkins #212] [Release 1.1.10] prepare release v1.1.10 --- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/pom.xml b/components/org.wso2.carbon.identity.organization.management.service/pom.xml index 70826ef6..8233419f 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.service/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.10-SNAPSHOT + 1.1.10 ../../pom.xml diff --git a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml index 3bf7c940..e6f20a06 100644 --- a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.10-SNAPSHOT + 1.1.10 ../../pom.xml diff --git a/pom.xml b/pom.xml index 8123a55a..5e1186de 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.10-SNAPSHOT + 1.1.10 4.0.0 pom WSO2 Carbon - Organization Management Core @@ -36,7 +36,7 @@ https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git - HEAD + v1.1.10 From ca04c09f11f523c2b86738ad5bb41b63d1885c31 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Fri, 5 Jul 2024 08:24:06 +0000 Subject: [PATCH 04/11] [WSO2 Release] [Jenkins #212] [Release 1.1.10] prepare for next development iteration --- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/pom.xml b/components/org.wso2.carbon.identity.organization.management.service/pom.xml index 8233419f..da17f655 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.service/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.10 + 1.1.11-SNAPSHOT ../../pom.xml diff --git a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml index e6f20a06..03622f47 100644 --- a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.10 + 1.1.11-SNAPSHOT ../../pom.xml diff --git a/pom.xml b/pom.xml index 5e1186de..6610d1e9 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.10 + 1.1.11-SNAPSHOT 4.0.0 pom WSO2 Carbon - Organization Management Core @@ -36,7 +36,7 @@ https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git - v1.1.10 + HEAD From 790cece56a52617163482e72745942df156cb264 Mon Sep 17 00:00:00 2001 From: Hasini Samarathunga Date: Tue, 9 Jul 2024 13:58:09 +0530 Subject: [PATCH 05/11] Service and DAO implementation for organization meta attributes GET API --- .../service/OrganizationManager.java | 19 ++++++++++ .../service/OrganizationManagerImpl.java | 14 ++++++++ .../service/constant/SQLConstants.java | 10 ++++++ .../dao/OrganizationManagementDAO.java | 20 +++++++++++ .../CacheBackedOrganizationManagementDAO.java | 10 ++++++ .../impl/OrganizationManagementDAOImpl.java | 36 ++++++++++++++++--- 6 files changed, 104 insertions(+), 5 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java index b3e4ca76..00b02fbe 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java @@ -333,4 +333,23 @@ default Organization addRootOrganization(int tenantId, Organization organization throw new NotImplementedException(); } + + /** + * List of organizations' meta attributes. + * + * @param limit The maximum number of records to be returned. + * @param after The pointer to next page. + * @param before The pointer to previous page. + * @param sortOrder The sort order, ascending or descending. + * @param filter The filter string. + * @param recursive Determines whether records should be retrieved in a recursive manner. + * @return The list of organizations' meta attributes. + * @throws OrganizationManagementException The exception thrown when listing organizations. + */ + default List getOrganizationsMetaAttributes(Integer limit, String after, String before, String sortOrder, + String filter, boolean recursive) + throws OrganizationManagementException { + + throw new NotImplementedException(); + } } diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java index 0a22b1c8..ab0d6e82 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java @@ -575,6 +575,20 @@ public Organization addRootOrganization(int tenantId, Organization organization) return organization; } + @Override + public List getOrganizationsMetaAttributes(Integer limit, String after, String before, String sortOrder, + String filter, boolean recursive) + throws OrganizationManagementException { + + List expressionNodes = getExpressionNodes(filter, after, before); + List filteringByParentIdExpressionNodes = getParentIdExpressionNodes(expressionNodes); + String orgId = resolveOrganizationId(getTenantDomain()); + expressionNodes.removeAll(filteringByParentIdExpressionNodes); + + return organizationManagementDAO.getOrganizationsMetaAttributes(recursive, limit, orgId, sortOrder, + expressionNodes, filteringByParentIdExpressionNodes); + } + private void updateTenantStatus(String status, String organizationId) throws OrganizationManagementServerException { if (StringUtils.equals(ACTIVE.toString(), status)) { diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java index c41756a6..1f97c90e 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java @@ -359,6 +359,16 @@ public class SQLConstants { "UM_ORG_ATTRIBUTE.UM_ATTRIBUTE_VALUE FROM UM_ORG INNER JOIN UM_ORG_ATTRIBUTE ON UM_ORG.UM_ID " + "= UM_ORG_ATTRIBUTE.UM_ORG_ID INNER JOIN (%s) AS FILTERED_ORG ON UM_ORG.UM_ID = FILTERED_ORG.UM_ID;"; + public static final String GET_ORGANIZATIONS_META_ATTRIBUTES = "SELECT DISTINCT " + + "UM_ORG_ATTRIBUTE.UM_ATTRIBUTE_KEY FROM UM_ORG_ATTRIBUTE " + + "JOIN UM_ORG ON UM_ORG_ATTRIBUTE.UM_ORG_ID = UM_ORG.UM_ID WHERE "; + + public static final String GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL = "UM_ORG.UM_ID IN " + + "(SELECT O.UM_ID FROM UM_ORG O JOIN UM_ORG_HIERARCHY OH ON O.UM_ID = OH.UM_ID " + + "WHERE OH.UM_PARENT_ID = (SELECT UM_ID FROM UM_ORG WHERE %s) " + + "AND OH.DEPTH %s) ORDER BY UM_ORG_ATTRIBUTE.UM_ATTRIBUTE_KEY %s " + + "LIMIT :" + SQLPlaceholders.DB_SCHEMA_LIMIT + ";"; + /** * SQL Placeholders. */ diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java index 7be63d06..fa9cfe38 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java @@ -409,4 +409,24 @@ String getAnAncestorOrganizationIdInGivenDepth(String organizationId, int depth) * @throws OrganizationManagementServerException The server exception thrown when adding a root organization. */ void addRootOrganization(Organization rootOrganization) throws OrganizationManagementServerException; + + /** + * Retrieve the list of organizations' meta attributes. + * + * @param recursive Determines whether records should be retrieved in a recursive manner. + * @param limit The maximum number of records to be returned. + * @param organizationId The super organization ID. + * @param sortOrder The sort order, ascending or descending. + * @param expressionNodes The list of filters excluding filtering by parentId. + * @param parentIdExpressionNodes The list of filters related to parentId. + * @return the list of organizations' meta attributes. + * @throws OrganizationManagementServerException The server exception thrown when retrieving the organizations. + */ + default List getOrganizationsMetaAttributes(boolean recursive, Integer limit, String organizationId, + String sortOrder, List expressionNodes, + List parentIdExpressionNodes) + throws OrganizationManagementServerException { + + throw new NotImplementedException(); + } } diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java index 834f1cdb..950f34b2 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java @@ -404,6 +404,16 @@ public void addRootOrganization(Organization organization) throws OrganizationMa organizationMgtDAO.addRootOrganization(organization); } + @Override + public List getOrganizationsMetaAttributes(boolean recursive, Integer limit, String organizationId, + String sortOrder, List expressionNodes, + List parentIdExpressionNodes) + throws OrganizationManagementServerException { + + return organizationMgtDAO.getOrganizationsMetaAttributes(recursive, limit, organizationId, sortOrder, + expressionNodes, parentIdExpressionNodes); + } + private TenantDomainCacheEntry getTenantDomainFromCache(String organizationId) { OrganizationIdCacheKey cacheKey = new OrganizationIdCacheKey(organizationId); diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java index 9b8257a8..91a77a7e 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java @@ -145,6 +145,8 @@ import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_CHILD_ORGANIZATION_IDS; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_BY_NAME; +import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_META_ATTRIBUTES; +import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_TAIL; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_TAIL_MSSQL; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_TAIL_ORACLE; @@ -987,19 +989,17 @@ private void appendFilterQuery(List expressionNodes, FilterQuery String operation = expressionNode.getOperation(); String value = expressionNode.getValue(); String attributeValue = expressionNode.getAttributeValue(); + String attributeName = ATTRIBUTE_COLUMN_MAP.get(attributeValue); + if (attributeValue.startsWith(ORGANIZATION_ATTRIBUTES_FIELD_PREFIX)) { - attributeValue = ORGANIZATION_ATTRIBUTES_FIELD; + attributeName = handleViewAttrKeyColumn(expressionNode, filterQueryBuilder); } - String attributeName = ATTRIBUTE_COLUMN_MAP.get(attributeValue); if (StringUtils.isNotBlank(attributeName) && StringUtils.isNotBlank(value) && StringUtils .isNotBlank(operation)) { if (VIEW_CREATED_TIME_COLUMN.equals(attributeName) || VIEW_LAST_MODIFIED_COLUMN.equals(attributeName)) { filterQueryBuilder.addTimestampFilterAttributes(FILTER_PLACEHOLDER_PREFIX); } - if (VIEW_ATTR_KEY_COLUMN.equals(attributeName)) { - attributeName = handleViewAttrKeyColumn(expressionNode, filterQueryBuilder); - } switch (operation) { case EQ: { equalFilterBuilder(count, value, attributeName, filter, filterQueryBuilder); @@ -1321,6 +1321,32 @@ public void addRootOrganization(Organization rootOrganization) throws Organizati } } + @Override + public List getOrganizationsMetaAttributes(boolean recursive, Integer limit, String organizationId, + String sortOrder, List expressionNodes, + List parentIdExpressionNodes) + throws OrganizationManagementServerException { + + FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes); + FilterQueryBuilder parentIdFilterQueryBuilder = buildParentIdFilterQuery(parentIdExpressionNodes); + + String sqlStmt = appendFilterQueries(GET_ORGANIZATIONS_META_ATTRIBUTES, filterQueryBuilder, + parentIdFilterQueryBuilder, GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL, + recursive, sortOrder); + + List organizationMetaAttributes; + NamedJdbcTemplate namedJdbcTemplate = Utils.getNewTemplate(); + try { + organizationMetaAttributes = namedJdbcTemplate.executeQuery(sqlStmt, + (resultSet, rowNumber) -> resultSet.getString(1), + namedPreparedStatement -> setPreparedStatementParams(namedPreparedStatement, organizationId, + null, limit, filterQueryBuilder, parentIdFilterQueryBuilder, null)); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS, e); + } + return organizationMetaAttributes; + } + private void createRootOrganizationHierarchy(String organizationId) throws OrganizationManagementServerException { NamedJdbcTemplate namedJdbcTemplate = Utils.getNewTemplate(); From aa05b497f2a3f72b6e9bac3ebaaf76cde7a9103b Mon Sep 17 00:00:00 2001 From: Hasini Samarathunga Date: Wed, 10 Jul 2024 17:34:01 +0530 Subject: [PATCH 06/11] Added unit testing and review suggestions --- .../service/OrganizationManager.java | 5 +- .../service/OrganizationManagerImpl.java | 5 +- .../OrganizationManagementConstants.java | 5 +- .../service/constant/SQLConstants.java | 12 ++++ .../dao/OrganizationManagementDAO.java | 12 ++-- .../CacheBackedOrganizationManagementDAO.java | 5 +- .../impl/OrganizationManagementDAOImpl.java | 54 +++++++++------ .../service/OrganizationManagerImplTest.java | 39 +++++++++-- .../OrganizationManagementDAOImplTest.java | 65 ++++++++++++++++--- 9 files changed, 151 insertions(+), 51 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java index 00b02fbe..44dc1a2a 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManager.java @@ -344,12 +344,13 @@ default Organization addRootOrganization(int tenantId, Organization organization * @param filter The filter string. * @param recursive Determines whether records should be retrieved in a recursive manner. * @return The list of organizations' meta attributes. - * @throws OrganizationManagementException The exception thrown when listing organizations. + * @throws OrganizationManagementException The exception thrown when listing organizations' meta attributes. */ default List getOrganizationsMetaAttributes(Integer limit, String after, String before, String sortOrder, String filter, boolean recursive) throws OrganizationManagementException { - throw new NotImplementedException(); + throw new OrganizationManagementServerException("getOrganizationsMetaAttributes is not implemented in " + + this.getClass().getName()); } } diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java index ab0d6e82..db03080e 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java @@ -581,12 +581,9 @@ public List getOrganizationsMetaAttributes(Integer limit, String after, throws OrganizationManagementException { List expressionNodes = getExpressionNodes(filter, after, before); - List filteringByParentIdExpressionNodes = getParentIdExpressionNodes(expressionNodes); String orgId = resolveOrganizationId(getTenantDomain()); - expressionNodes.removeAll(filteringByParentIdExpressionNodes); - return organizationManagementDAO.getOrganizationsMetaAttributes(recursive, limit, orgId, sortOrder, - expressionNodes, filteringByParentIdExpressionNodes); + expressionNodes); } private void updateTenantStatus(String status, String organizationId) throws OrganizationManagementServerException { diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java index 75c15c48..715d20a4 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java @@ -723,7 +723,10 @@ public enum ErrorMessages { "organization with ID: %s."), ERROR_CODE_ERROR_REVOKING_SHARED_APP_TOKENS("65138", "Error while revoking tokens issued for " + "shared application.", "Server encountered an error while revoking tokens issued for application: " + - "%s in organization with ID: %s"); + "%s in organization with ID: %s"), + ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS_META_ATTRIBUTES("65139", "Unable to retrieve " + + "the organizations' meta attributes.", "Server encountered an error while retrieving " + + "the organizations' meta attributes."); private final String code; private final String message; diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java index 1f97c90e..8f1d9d22 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/SQLConstants.java @@ -369,6 +369,18 @@ public class SQLConstants { "AND OH.DEPTH %s) ORDER BY UM_ORG_ATTRIBUTE.UM_ATTRIBUTE_KEY %s " + "LIMIT :" + SQLPlaceholders.DB_SCHEMA_LIMIT + ";"; + public static final String GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL_ORACLE = "UM_ORG.UM_ID IN " + + "(SELECT O.UM_ID FROM UM_ORG O JOIN UM_ORG_HIERARCHY OH ON O.UM_ID = OH.UM_ID " + + "WHERE OH.UM_PARENT_ID = (SELECT UM_ID FROM UM_ORG WHERE %s) " + + "AND OH.DEPTH %s) ORDER BY UM_ORG_ATTRIBUTE.UM_ATTRIBUTE_KEY %s " + + "FETCH FIRST :" + SQLPlaceholders.DB_SCHEMA_LIMIT + "; ROWS ONLY;"; + + public static final String GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL_MSSQL = "UM_ORG.UM_ID IN " + + "(SELECT O.UM_ID FROM UM_ORG O JOIN UM_ORG_HIERARCHY OH ON O.UM_ID = OH.UM_ID " + + "WHERE OH.UM_PARENT_ID = (SELECT UM_ID FROM UM_ORG WHERE %s) " + + "AND OH.DEPTH %s) ORDER BY UM_ORG_ATTRIBUTE.UM_ATTRIBUTE_KEY %s " + + "OFFSET 0 ROWS FETCH NEXT :" + SQLPlaceholders.DB_SCHEMA_LIMIT + "; ROWS ONLY;"; + /** * SQL Placeholders. */ diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java index fa9cfe38..85776c60 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/OrganizationManagementDAO.java @@ -417,16 +417,16 @@ String getAnAncestorOrganizationIdInGivenDepth(String organizationId, int depth) * @param limit The maximum number of records to be returned. * @param organizationId The super organization ID. * @param sortOrder The sort order, ascending or descending. - * @param expressionNodes The list of filters excluding filtering by parentId. - * @param parentIdExpressionNodes The list of filters related to parentId. + * @param expressionNodes The list of filters. * @return the list of organizations' meta attributes. - * @throws OrganizationManagementServerException The server exception thrown when retrieving the organizations. + * @throws OrganizationManagementServerException The server exception thrown when retrieving the organizations' + * meta attributes. */ default List getOrganizationsMetaAttributes(boolean recursive, Integer limit, String organizationId, - String sortOrder, List expressionNodes, - List parentIdExpressionNodes) + String sortOrder, List expressionNodes) throws OrganizationManagementServerException { - throw new NotImplementedException(); + throw new OrganizationManagementServerException("getOrganizationsMetaAttributes is not implemented in " + + this.getClass().getName()); } } diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java index 950f34b2..1140e6f9 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/CacheBackedOrganizationManagementDAO.java @@ -406,12 +406,11 @@ public void addRootOrganization(Organization organization) throws OrganizationMa @Override public List getOrganizationsMetaAttributes(boolean recursive, Integer limit, String organizationId, - String sortOrder, List expressionNodes, - List parentIdExpressionNodes) + String sortOrder, List expressionNodes) throws OrganizationManagementServerException { return organizationMgtDAO.getOrganizationsMetaAttributes(recursive, limit, organizationId, sortOrder, - expressionNodes, parentIdExpressionNodes); + expressionNodes); } private TenantDomainCacheEntry getTenantDomainFromCache(String organizationId) { diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java index 91a77a7e..7c880fe2 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java @@ -83,6 +83,7 @@ import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_CHILD_ORGANIZATIONS; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS_BY_NAME; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS_META_ATTRIBUTES; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_ORGANIZATION_BY_ID; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_ORGANIZATION_DEPTH; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RETRIEVING_ORGANIZATION_ID_BY_NAME; @@ -147,6 +148,8 @@ import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_BY_NAME; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_META_ATTRIBUTES; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL; +import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL_MSSQL; +import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL_ORACLE; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_TAIL; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_TAIL_MSSQL; import static org.wso2.carbon.identity.organization.management.service.constant.SQLConstants.GET_ORGANIZATIONS_TAIL_ORACLE; @@ -1321,18 +1324,28 @@ public void addRootOrganization(Organization rootOrganization) throws Organizati } } + private void createRootOrganizationHierarchy(String organizationId) throws OrganizationManagementServerException { + + NamedJdbcTemplate namedJdbcTemplate = Utils.getNewTemplate(); + try { + namedJdbcTemplate.withTransaction(template -> { + template.executeInsert(INSERT_ROOT_ORGANIZATION_HIERARCHY, namedPreparedStatement -> { + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_ID, organizationId); + }, null, false); + return null; + }); + } catch (TransactionException e) { + throw handleServerException(ERROR_CODE_ERROR_ADDING_ORGANIZATION_HIERARCHY_DATA, e); + } + } + @Override public List getOrganizationsMetaAttributes(boolean recursive, Integer limit, String organizationId, - String sortOrder, List expressionNodes, - List parentIdExpressionNodes) + String sortOrder, List expressionNodes) throws OrganizationManagementServerException { FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes); - FilterQueryBuilder parentIdFilterQueryBuilder = buildParentIdFilterQuery(parentIdExpressionNodes); - - String sqlStmt = appendFilterQueries(GET_ORGANIZATIONS_META_ATTRIBUTES, filterQueryBuilder, - parentIdFilterQueryBuilder, GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL, - recursive, sortOrder); + String sqlStmt = getOrgMetaAttributesSqlStmt(recursive, sortOrder, filterQueryBuilder); List organizationMetaAttributes; NamedJdbcTemplate namedJdbcTemplate = Utils.getNewTemplate(); @@ -1340,26 +1353,27 @@ public List getOrganizationsMetaAttributes(boolean recursive, Integer li organizationMetaAttributes = namedJdbcTemplate.executeQuery(sqlStmt, (resultSet, rowNumber) -> resultSet.getString(1), namedPreparedStatement -> setPreparedStatementParams(namedPreparedStatement, organizationId, - null, limit, filterQueryBuilder, parentIdFilterQueryBuilder, null)); + null, limit, filterQueryBuilder, new FilterQueryBuilder(), null)); } catch (DataAccessException e) { - throw handleServerException(ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS, e); + throw handleServerException(ERROR_CODE_ERROR_RETRIEVING_ORGANIZATIONS_META_ATTRIBUTES, e); } return organizationMetaAttributes; } - private void createRootOrganizationHierarchy(String organizationId) throws OrganizationManagementServerException { + private static String getOrgMetaAttributesSqlStmt(boolean recursive, String sortOrder, + FilterQueryBuilder filterQueryBuilder) + throws OrganizationManagementServerException { - NamedJdbcTemplate namedJdbcTemplate = Utils.getNewTemplate(); - try { - namedJdbcTemplate.withTransaction(template -> { - template.executeInsert(INSERT_ROOT_ORGANIZATION_HIERARCHY, namedPreparedStatement -> { - namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_ID, organizationId); - }, null, false); - return null; - }); - } catch (TransactionException e) { - throw handleServerException(ERROR_CODE_ERROR_ADDING_ORGANIZATION_HIERARCHY_DATA, e); + String orgSqlStmtTail; + if (isOracleDB()) { + orgSqlStmtTail = GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL_ORACLE; + } else if (isMSSqlDB()) { + orgSqlStmtTail = GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL_MSSQL; + } else { + orgSqlStmtTail = GET_ORGANIZATIONS_META_ATTRIBUTES_TAIL; } + return GET_ORGANIZATIONS_META_ATTRIBUTES + filterQueryBuilder.getFilterQuery() + + String.format(orgSqlStmtTail, SET_ID, recursive ? "> 0" : "= 1", sortOrder); } private void equalFilterBuilder(int count, String value, String attributeName, StringBuilder filter, diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImplTest.java b/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImplTest.java index 52033c87..50428d03 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImplTest.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImplTest.java @@ -85,6 +85,7 @@ public class OrganizationManagerImplTest { private static final String ORG_ATTRIBUTE_VALUE_COUNTRY = "Sri Lanka"; private static final String ORG_ATTRIBUTE_KEY_CITY = "city"; private static final String ORG_ATTRIBUTE_VALUE_CITY = "Colombo"; + private static final String ORG_ATTRIBUTE_KEY_CAPITAL = "capital"; private static final String SUPER_ORG_ID = "10084a8d-113f-4211-a0d5-efe36b082211"; private static final String ROOT_ORG = "custom-root-org"; private static final String ORG1_ID = "org_id_1"; @@ -140,11 +141,9 @@ public void setUp() throws Exception { Organization organization3 = getOrganization(ORG3_ID, ORG3_NAME, ORG_DESCRIPTION, SUPER_ORG_ID, TENANT.toString()); - OrganizationAttribute organizationAttribute = new OrganizationAttribute(ORG_ATTRIBUTE_KEY_COUNTRY, - ORG_ATTRIBUTE_VALUE_COUNTRY); - organization3.setAttribute(organizationAttribute); - organizationAttribute = new OrganizationAttribute(ORG_ATTRIBUTE_KEY_CITY, ORG_ATTRIBUTE_VALUE_CITY); - organization3.setAttribute(organizationAttribute); + setOrganizationAttributes(organization3, ORG_ATTRIBUTE_KEY_COUNTRY, ORG_ATTRIBUTE_VALUE_COUNTRY); + setOrganizationAttributes(organization3, ORG_ATTRIBUTE_KEY_CITY, ORG_ATTRIBUTE_VALUE_CITY); + setOrganizationAttributes(organization2, ORG_ATTRIBUTE_KEY_CAPITAL, ORG_ATTRIBUTE_VALUE_CITY); organizationManagementDAO.addOrganization(organization1); organizationManagementDAO.addOrganization(organization2); @@ -435,6 +434,30 @@ public void testGetOrganizationsWithInvalidPaginationAttribute() throws Exceptio "name co xyz", false); } + @DataProvider(name = "dataForGetOrganizationsMetaAttributes") + public Object[][] dataForGetOrganizationsMetaAttributes() { + + return new Object[][]{ + {"attributes eq country", false}, + {"attributes sw c and attributes ew try", false}, + {"attributes co cap", true}, + }; + } + + @Test(dataProvider = "dataForGetOrganizationsMetaAttributes") + public void testGetOrganizationsMetaAttributes(String filter, boolean isRecursive) throws Exception { + + TestUtils.mockCarbonContext(SUPER_ORG_ID); + List metaAttributes = organizationManager.getOrganizationsMetaAttributes(10, null, + null, "ASC", filter, isRecursive); + assertEquals(metaAttributes.size(), 1); + if (isRecursive) { + assertEquals(metaAttributes.get(0), ORG_ATTRIBUTE_KEY_CAPITAL); + } else { + assertEquals(metaAttributes.get(0), ORG_ATTRIBUTE_KEY_COUNTRY); + } + } + @Test(expectedExceptions = OrganizationManagementClientException.class) public void testDeleteOrganization() throws Exception { @@ -646,6 +669,12 @@ public void testGetParentOrganizationId() throws OrganizationManagementException Assert.assertEquals(organizationManager.getParentOrganizationId(ORG2_ID), ORG1_ID); } + private void setOrganizationAttributes(Organization organization, String key, String value) { + + OrganizationAttribute organizationAttribute = new OrganizationAttribute(key, value); + organization.setAttribute(organizationAttribute); + } + private void mockUtils() { mockedUtilities = Mockito.mockStatic(Utils.class, Mockito.withSettings() diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImplTest.java b/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImplTest.java index 0d5ade02..3f2389f4 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImplTest.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/test/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImplTest.java @@ -43,6 +43,7 @@ import java.util.TimeZone; import static java.time.ZoneOffset.UTC; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ORGANIZATION_ATTRIBUTES_FIELD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ORGANIZATION_ATTRIBUTES_FIELD_PREFIX; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationTypes.STRUCTURAL; import static org.wso2.carbon.identity.organization.management.service.util.Utils.generateUniqueID; @@ -56,18 +57,27 @@ public class OrganizationManagementDAOImplTest { private OrganizationManagementDAO organizationManagementDAO = new OrganizationManagementDAOImpl(); private static final Calendar CALENDAR = Calendar.getInstance(TimeZone.getTimeZone(UTC)); private static final String ATTRIBUTE_KEY = "country"; + private static final String ATTRIBUTE_KEY_REGION = "region"; private static final String ATTRIBUTE_VALUE = "Sri Lanka"; private static final String ORG_NAME = "XYZ builders"; + private static final String CHILD_ORG_NAME = "ABC builders"; + private static final String ORG_DESCRIPTION = "This is a construction company."; private static final String INVALID_DATA = "invalid data"; private static final String SUPER_ORG_ID = "10084a8d-113f-4211-a0d5-efe36b082211"; private String orgId; + private String childOrgId; @BeforeClass public void setUp() throws Exception { initiateH2Base(); mockDataSource(); - storeChildOrganization(SUPER_ORG_ID); + + orgId = generateUniqueID(); + childOrgId = generateUniqueID(); + storeChildOrganization(orgId, ORG_NAME, ORG_DESCRIPTION, SUPER_ORG_ID); + storeChildOrganization(childOrgId, CHILD_ORG_NAME, ORG_DESCRIPTION, orgId); + storeOrganizationAttributes(childOrgId, ATTRIBUTE_KEY_REGION, ATTRIBUTE_VALUE); } @AfterClass @@ -207,6 +217,34 @@ public void testFilterOrganizationsByMetaAttributes(String attributeValue, Strin Assert.assertEquals(organizations.get(0).getAttributes().get(0).getValue(), ATTRIBUTE_VALUE); } + @DataProvider(name = "dataForGetOrganizationsMetaAttributes") + public Object[][] dataForGetOrganizationsMetaAttributes() { + + return new Object[][]{ + {ORGANIZATION_ATTRIBUTES_FIELD, "eq", ATTRIBUTE_KEY, false}, + {ORGANIZATION_ATTRIBUTES_FIELD, "eq", ATTRIBUTE_KEY_REGION, true}, + }; + } + + @Test(dataProvider = "dataForGetOrganizationsMetaAttributes") + public void testGetOrganizationsMetaAttributes(String attributeValue, String operation, String value, + boolean isRecursive) throws OrganizationManagementServerException { + + TestUtils.mockCarbonContext(SUPER_ORG_ID); + ExpressionNode expressionNode = getExpressionNode(attributeValue, operation, value); + List expressionNodes = new ArrayList<>(); + expressionNodes.add(expressionNode); + List metaAttributes = organizationManagementDAO.getOrganizationsMetaAttributes(isRecursive, 10, + SUPER_ORG_ID, "DESC", expressionNodes); + + Assert.assertEquals(metaAttributes.size(), 1); + if (isRecursive) { + Assert.assertEquals(metaAttributes.get(0), ATTRIBUTE_KEY_REGION); + } else { + Assert.assertEquals(metaAttributes.get(0), ATTRIBUTE_KEY); + } + } + @DataProvider(name = "dataForHasChildOrganizations") public Object[][] dataForHasChildOrganizations() { @@ -220,7 +258,7 @@ public Object[][] dataForHasChildOrganizations() { public void testHasChildOrganizations(String id) throws Exception { boolean hasChildOrganizations = organizationManagementDAO.hasChildOrganizations(id); - if (StringUtils.equals(id, orgId)) { + if (StringUtils.equals(id, childOrgId)) { Assert.assertFalse(hasChildOrganizations); } else if (StringUtils.equals(id, SUPER_ORG_ID)) { Assert.assertTrue(hasChildOrganizations); @@ -257,12 +295,11 @@ public void testDeleteOrganization() throws Exception { Assert.assertNull(organizationManagementDAO.getOrganization(id)); } - private void storeChildOrganization(String parentId) throws Exception { + private void storeChildOrganization(String id, String name, String description, String parentId) throws Exception { - orgId = generateUniqueID(); - storeOrganization(orgId, "XYZ builders", "This is a construction company.", parentId); - storeOrganizationHierarchy(orgId, parentId); - storeOrganizationAttributes(orgId); + storeOrganization(id, name, description, parentId); + storeOrganizationHierarchy(id, parentId); + storeOrganizationAttributes(id, ATTRIBUTE_KEY, ATTRIBUTE_VALUE); } private void storeOrganization(String id, String name, String description, String parentId) @@ -293,17 +330,25 @@ private void storeOrganizationHierarchy(String id, String parentId) throws Excep statement.setString(3, "1"); statement.execute(); } + try (Connection connection = getConnection()) { + String sql = "INSERT INTO UM_ORG_HIERARCHY (UM_PARENT_ID, UM_ID, DEPTH) SELECT UM_PARENT_ID, ?, " + + "DEPTH + 1 FROM UM_ORG_HIERARCHY WHERE UM_ORG_HIERARCHY.UM_ID = ? AND UM_PARENT_ID <> UM_ID"; + PreparedStatement statement = connection.prepareStatement(sql); + statement.setString(1, id); + statement.setString(2, parentId); + statement.execute(); + } } - private void storeOrganizationAttributes(String id) throws Exception { + private void storeOrganizationAttributes(String id, String attributeKey, String attributeValue) throws Exception { try (Connection connection = getConnection()) { String sql = "INSERT INTO UM_ORG_ATTRIBUTE (UM_ORG_ID, UM_ATTRIBUTE_KEY, UM_ATTRIBUTE_VALUE) VALUES " + "( ?, ?, ?)"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1, id); - statement.setString(2, ATTRIBUTE_KEY); - statement.setString(3, ATTRIBUTE_VALUE); + statement.setString(2, attributeKey); + statement.setString(3, attributeValue); statement.execute(); } } From 0b3bcac9172571b1292d217f3809b2db3e1f11f6 Mon Sep 17 00:00:00 2001 From: Hasini Samarathunga Date: Fri, 12 Jul 2024 18:24:12 +0530 Subject: [PATCH 07/11] Added cursor-based pagination for meta attributes --- .../service/OrganizationManagerImpl.java | 47 +++++++++++++++---- .../OrganizationManagementConstants.java | 6 +++ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java index db03080e..9c0586a9 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java @@ -78,6 +78,7 @@ import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_DEACTIVATING_ORGANIZATION_TENANT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_DEACTIVATING_ROOT_ORGANIZATION_TENANT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_VALIDATING_ORGANIZATION_OWNER; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_CURSOR_FOR_META_ATTRIBUTE_PAGINATION; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_FILTER_FORMAT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_FILTER_TIMESTAMP_FORMAT; @@ -128,7 +129,9 @@ import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationTypes.STRUCTURAL; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationTypes.TENANT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_AFTER; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_AFTER_ATTRIBUTE; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_BEFORE; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_BEFORE_ATTRIBUTE; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PARENT_ID_FIELD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PATCH_OP_ADD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PATCH_OP_REMOVE; @@ -322,7 +325,7 @@ private List getOrganizationsBasicInfo(boolean authorizedSubO String applicationAudience) throws OrganizationManagementException { - List expressionNodes = getExpressionNodes(filter, after, before); + List expressionNodes = getExpressionNodes(filter, after, before, false); List filteringByParentIdExpressionNodes = getParentIdExpressionNodes(expressionNodes); String orgId = resolveOrganizationId(getTenantDomain()); expressionNodes.removeAll(filteringByParentIdExpressionNodes); @@ -338,7 +341,7 @@ private List getOrganizationList(Integer limit, String after, Stri String filter, boolean recursive) throws OrganizationManagementException { - List expressionNodes = getExpressionNodes(filter, after, before); + List expressionNodes = getExpressionNodes(filter, after, before, false); List filteringByParentIdExpressionNodes = getParentIdExpressionNodes(expressionNodes); String orgId = resolveOrganizationId(getTenantDomain()); expressionNodes.removeAll(filteringByParentIdExpressionNodes); @@ -580,7 +583,7 @@ public List getOrganizationsMetaAttributes(Integer limit, String after, String filter, boolean recursive) throws OrganizationManagementException { - List expressionNodes = getExpressionNodes(filter, after, before); + List expressionNodes = getExpressionNodes(filter, after, before, true); String orgId = resolveOrganizationId(getTenantDomain()); return organizationManagementDAO.getOrganizationsMetaAttributes(recursive, limit, orgId, sortOrder, expressionNodes); @@ -913,14 +916,17 @@ private void validateOrganizationStatusUpdate(String value, String organizationI } } - private List getExpressionNodes(String filter, String after, String before) + private List getExpressionNodes(String filter, String after, String before, + boolean isFilteringMetaAttributes) throws OrganizationManagementClientException { List expressionNodes = new ArrayList<>(); if (StringUtils.isBlank(filter)) { filter = StringUtils.EMPTY; } - String paginatedFilter = getPaginatedFilter(filter, after, before); + String paginatedFilter = isFilteringMetaAttributes ? + getPaginatedFilterForMetaAttributes(filter, after, before) : + getPaginatedFilter(filter, after, before); try { if (StringUtils.isNotBlank(paginatedFilter)) { FilterTreeBuilder filterTreeBuilder = new FilterTreeBuilder(paginatedFilter); @@ -940,13 +946,13 @@ private String getPaginatedFilter(String paginatedFilter, String after, String b if (StringUtils.isNotBlank(before)) { String decodedString = new String(Base64.getDecoder().decode(before), StandardCharsets.UTF_8); Timestamp.valueOf(decodedString); - paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and before gt " + decodedString : - "before gt " + decodedString; + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and before lt " + decodedString : + "before lt " + decodedString; } else if (StringUtils.isNotBlank(after)) { String decodedString = new String(Base64.getDecoder().decode(after), StandardCharsets.UTF_8); Timestamp.valueOf(decodedString); - paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and after lt " + decodedString : - "after lt " + decodedString; + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and after gt " + decodedString : + "after gt " + decodedString; } } catch (IllegalArgumentException e) { throw handleClientException(ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION); @@ -954,6 +960,25 @@ private String getPaginatedFilter(String paginatedFilter, String after, String b return paginatedFilter; } + private String getPaginatedFilterForMetaAttributes(String paginatedFilter, String after, String before) + throws OrganizationManagementClientException { + + try { + if (StringUtils.isNotBlank(before)) { + String decodedString = new String(Base64.getDecoder().decode(before), StandardCharsets.UTF_8); + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and attributeBefore lt " + + decodedString : "attributeBefore lt " + decodedString; + } else if (StringUtils.isNotBlank(after)) { + String decodedString = new String(Base64.getDecoder().decode(after), StandardCharsets.UTF_8); + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and attributeAfter gt " + + decodedString : "attributeAfter gt " + decodedString; + } + } catch (IllegalArgumentException e) { + throw handleClientException(ERROR_CODE_INVALID_CURSOR_FOR_META_ATTRIBUTE_PAGINATION); + } + return paginatedFilter; + } + /** * Sets the expression nodes required for the retrieval of organizations from the database. * @@ -996,7 +1021,9 @@ private boolean isFilteringAttributeNotSupported(String attributeValue) { !attributeValue.equalsIgnoreCase(ORGANIZATION_ATTRIBUTES_FIELD) && !attributeValue.equalsIgnoreCase(PARENT_ID_FIELD) && !attributeValue.equalsIgnoreCase(PAGINATION_AFTER) && - !attributeValue.equalsIgnoreCase(PAGINATION_BEFORE); + !attributeValue.equalsIgnoreCase(PAGINATION_BEFORE) && + !attributeValue.equalsIgnoreCase(PAGINATION_AFTER_ATTRIBUTE) && + !attributeValue.equalsIgnoreCase(PAGINATION_BEFORE_ATTRIBUTE); } private void createTenant(String domain, Organization organization) throws OrganizationManagementException { diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java index 715d20a4..b3af3b57 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java @@ -67,6 +67,8 @@ public class OrganizationManagementConstants { public static final String ORGANIZATION_ATTRIBUTES_FIELD_PREFIX = "attributes."; public static final String PAGINATION_AFTER = "after"; public static final String PAGINATION_BEFORE = "before"; + public static final String PAGINATION_AFTER_ATTRIBUTE = "attributeBefore"; + public static final String PAGINATION_BEFORE_ATTRIBUTE = "attributeAfter"; public static final String CREATE_ORGANIZATION_ADMIN_PERMISSION = "/permission/admin/"; public static final String BASE_ORGANIZATION_PERMISSION = "/permission/admin/manage/identity/organizationmgt"; public static final String CREATE_ORGANIZATION_PERMISSION = "/permission/admin/manage/identity/organizationmgt/" + @@ -157,6 +159,8 @@ public static class Filter { attributeColumnMap.put(ORGANIZATION_ATTRIBUTES_FIELD, VIEW_ATTR_KEY_COLUMN); attributeColumnMap.put(PAGINATION_AFTER, VIEW_CREATED_TIME_COLUMN); attributeColumnMap.put(PAGINATION_BEFORE, VIEW_CREATED_TIME_COLUMN); + attributeColumnMap.put(PAGINATION_AFTER_ATTRIBUTE, VIEW_ATTR_KEY_COLUMN); + attributeColumnMap.put(PAGINATION_BEFORE_ATTRIBUTE, VIEW_ATTR_KEY_COLUMN); } /** @@ -232,6 +236,8 @@ public enum ErrorMessages { "'limit' shouldn't be negative."), ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION("60026", "Unable to retrieve organizations.", "Invalid " + "cursor used for pagination."), + ERROR_CODE_INVALID_CURSOR_FOR_META_ATTRIBUTE_PAGINATION("60027", "Unable to retrieve " + + "organizations' meta attributes.", "Invalid cursor used for pagination."), ERROR_CODE_UNSUPPORTED_ORGANIZATION_STATUS("60028", "Unsupported status provided.", "Organization status must be 'ACTIVE' or 'DISABLED'."), ERROR_CODE_ACTIVE_CHILD_ORGANIZATIONS_EXIST("60029", "Active child organizations exist.", From 2f024e5c8d17db1476fb3b1e5a8294a352bf9629 Mon Sep 17 00:00:00 2001 From: Hasini Samarathunga Date: Tue, 16 Jul 2024 15:30:34 +0530 Subject: [PATCH 08/11] Fixed wrong pagination results returned from the GET organizations DAO --- .../service/dao/impl/OrganizationManagementDAOImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java index 9b8257a8..02d9d81e 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java @@ -1605,7 +1605,7 @@ private void setFilterAttributes(NamedPreparedStatement namedPreparedStatement, } for (Map.Entry entry : filterAttributeValue.entrySet()) { if (timestampTypeAttributes.contains(entry.getKey())) { - namedPreparedStatement.setTimeStamp(entry.getKey(), Timestamp.valueOf(entry.getValue()), CALENDAR); + namedPreparedStatement.setTimeStamp(entry.getKey(), Timestamp.valueOf(entry.getValue()), null); } else { namedPreparedStatement.setString(entry.getKey(), entry.getValue()); } From c0ff5dcd484b5cc1a82f14b7aca76b19a48766fd Mon Sep 17 00:00:00 2001 From: Hasini Samarathunga Date: Fri, 19 Jul 2024 16:52:20 +0530 Subject: [PATCH 09/11] Added review suggestions --- .../service/OrganizationManagerImpl.java | 53 +++++++++---------- .../OrganizationManagementConstants.java | 13 ++--- .../impl/OrganizationManagementDAOImpl.java | 20 ++++--- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java index 9c0586a9..107168cb 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/OrganizationManagerImpl.java @@ -62,10 +62,12 @@ import java.util.stream.Collectors; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.AND; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ASC_SORT_ORDER; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.CO; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.CREATOR_EMAIL; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.CREATOR_ID; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.CREATOR_USERNAME; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.DESC_SORT_ORDER; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.EW; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ACTIVE_CHILD_ORGANIZATIONS_EXIST; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ATTRIBUTE_KEY_MISSING; @@ -78,7 +80,6 @@ import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_DEACTIVATING_ORGANIZATION_TENANT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_DEACTIVATING_ROOT_ORGANIZATION_TENANT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_VALIDATING_ORGANIZATION_OWNER; -import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_CURSOR_FOR_META_ATTRIBUTE_PAGINATION; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_FILTER_FORMAT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_INVALID_FILTER_TIMESTAMP_FORMAT; @@ -129,9 +130,7 @@ import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationTypes.STRUCTURAL; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationTypes.TENANT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_AFTER; -import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_AFTER_ATTRIBUTE; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_BEFORE; -import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_BEFORE_ATTRIBUTE; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PARENT_ID_FIELD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PATCH_OP_ADD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PATCH_OP_REMOVE; @@ -325,7 +324,7 @@ private List getOrganizationsBasicInfo(boolean authorizedSubO String applicationAudience) throws OrganizationManagementException { - List expressionNodes = getExpressionNodes(filter, after, before, false); + List expressionNodes = getExpressionNodes(filter, after, before, DESC_SORT_ORDER); List filteringByParentIdExpressionNodes = getParentIdExpressionNodes(expressionNodes); String orgId = resolveOrganizationId(getTenantDomain()); expressionNodes.removeAll(filteringByParentIdExpressionNodes); @@ -341,7 +340,7 @@ private List getOrganizationList(Integer limit, String after, Stri String filter, boolean recursive) throws OrganizationManagementException { - List expressionNodes = getExpressionNodes(filter, after, before, false); + List expressionNodes = getExpressionNodes(filter, after, before, DESC_SORT_ORDER); List filteringByParentIdExpressionNodes = getParentIdExpressionNodes(expressionNodes); String orgId = resolveOrganizationId(getTenantDomain()); expressionNodes.removeAll(filteringByParentIdExpressionNodes); @@ -583,7 +582,7 @@ public List getOrganizationsMetaAttributes(Integer limit, String after, String filter, boolean recursive) throws OrganizationManagementException { - List expressionNodes = getExpressionNodes(filter, after, before, true); + List expressionNodes = getExpressionNodes(filter, after, before, ASC_SORT_ORDER); String orgId = resolveOrganizationId(getTenantDomain()); return organizationManagementDAO.getOrganizationsMetaAttributes(recursive, limit, orgId, sortOrder, expressionNodes); @@ -917,16 +916,18 @@ private void validateOrganizationStatusUpdate(String value, String organizationI } private List getExpressionNodes(String filter, String after, String before, - boolean isFilteringMetaAttributes) + String paginationSortOrder) throws OrganizationManagementClientException { List expressionNodes = new ArrayList<>(); if (StringUtils.isBlank(filter)) { filter = StringUtils.EMPTY; } - String paginatedFilter = isFilteringMetaAttributes ? - getPaginatedFilterForMetaAttributes(filter, after, before) : - getPaginatedFilter(filter, after, before); + // paginationSortOrder specifies the sorting order for the pagination cursor. + // E.g., descending for creation time (most recent first) or ascending for metadata name (alphabetical). + String paginatedFilter = paginationSortOrder.equals(ASC_SORT_ORDER) ? + getPaginatedFilterForAscendingOrder(filter, after, before) : + getPaginatedFilterForDescendingOrder(filter, after, before); try { if (StringUtils.isNotBlank(paginatedFilter)) { FilterTreeBuilder filterTreeBuilder = new FilterTreeBuilder(paginatedFilter); @@ -939,20 +940,18 @@ private List getExpressionNodes(String filter, String after, Str return expressionNodes; } - private String getPaginatedFilter(String paginatedFilter, String after, String before) throws - OrganizationManagementClientException { + private String getPaginatedFilterForAscendingOrder(String paginatedFilter, String after, String before) + throws OrganizationManagementClientException { try { if (StringUtils.isNotBlank(before)) { String decodedString = new String(Base64.getDecoder().decode(before), StandardCharsets.UTF_8); - Timestamp.valueOf(decodedString); - paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and before lt " + decodedString : - "before lt " + decodedString; + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and before lt " + + decodedString : "before lt " + decodedString; } else if (StringUtils.isNotBlank(after)) { String decodedString = new String(Base64.getDecoder().decode(after), StandardCharsets.UTF_8); - Timestamp.valueOf(decodedString); - paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and after gt " + decodedString : - "after gt " + decodedString; + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and after gt " + + decodedString : "after gt " + decodedString; } } catch (IllegalArgumentException e) { throw handleClientException(ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION); @@ -960,21 +959,23 @@ private String getPaginatedFilter(String paginatedFilter, String after, String b return paginatedFilter; } - private String getPaginatedFilterForMetaAttributes(String paginatedFilter, String after, String before) + private String getPaginatedFilterForDescendingOrder(String paginatedFilter, String after, String before) throws OrganizationManagementClientException { try { if (StringUtils.isNotBlank(before)) { String decodedString = new String(Base64.getDecoder().decode(before), StandardCharsets.UTF_8); - paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and attributeBefore lt " - + decodedString : "attributeBefore lt " + decodedString; + Timestamp.valueOf(decodedString); + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and before gt " + decodedString : + "before gt " + decodedString; } else if (StringUtils.isNotBlank(after)) { String decodedString = new String(Base64.getDecoder().decode(after), StandardCharsets.UTF_8); - paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and attributeAfter gt " - + decodedString : "attributeAfter gt " + decodedString; + Timestamp.valueOf(decodedString); + paginatedFilter += StringUtils.isNotBlank(paginatedFilter) ? " and after lt " + decodedString : + "after lt " + decodedString; } } catch (IllegalArgumentException e) { - throw handleClientException(ERROR_CODE_INVALID_CURSOR_FOR_META_ATTRIBUTE_PAGINATION); + throw handleClientException(ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION); } return paginatedFilter; } @@ -1021,9 +1022,7 @@ private boolean isFilteringAttributeNotSupported(String attributeValue) { !attributeValue.equalsIgnoreCase(ORGANIZATION_ATTRIBUTES_FIELD) && !attributeValue.equalsIgnoreCase(PARENT_ID_FIELD) && !attributeValue.equalsIgnoreCase(PAGINATION_AFTER) && - !attributeValue.equalsIgnoreCase(PAGINATION_BEFORE) && - !attributeValue.equalsIgnoreCase(PAGINATION_AFTER_ATTRIBUTE) && - !attributeValue.equalsIgnoreCase(PAGINATION_BEFORE_ATTRIBUTE); + !attributeValue.equalsIgnoreCase(PAGINATION_BEFORE); } private void createTenant(String domain, Organization organization) throws OrganizationManagementException { diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java index b3af3b57..a603ec6b 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/constant/OrganizationManagementConstants.java @@ -67,8 +67,6 @@ public class OrganizationManagementConstants { public static final String ORGANIZATION_ATTRIBUTES_FIELD_PREFIX = "attributes."; public static final String PAGINATION_AFTER = "after"; public static final String PAGINATION_BEFORE = "before"; - public static final String PAGINATION_AFTER_ATTRIBUTE = "attributeBefore"; - public static final String PAGINATION_BEFORE_ATTRIBUTE = "attributeAfter"; public static final String CREATE_ORGANIZATION_ADMIN_PERMISSION = "/permission/admin/"; public static final String BASE_ORGANIZATION_PERMISSION = "/permission/admin/manage/identity/organizationmgt"; public static final String CREATE_ORGANIZATION_PERMISSION = "/permission/admin/manage/identity/organizationmgt/" + @@ -82,7 +80,8 @@ public class OrganizationManagementConstants { public static final List ALL_ORGANIZATION_PERMISSIONS = Collections.unmodifiableList(Arrays .asList(CREATE_ORGANIZATION_PERMISSION, VIEW_ORGANIZATION_PERMISSION, UPDATE_ORGANIZATION_PERMISSION, DELETE_ORGANIZATION_PERMISSION)); - public static final String ROOT_TENANT_DOMAIN = "RootTenantDomain"; + public static final String DESC_SORT_ORDER = "DESC"; + public static final String ASC_SORT_ORDER = "ASC"; public static final String EQ = "eq"; public static final String CO = "co"; @@ -159,8 +158,6 @@ public static class Filter { attributeColumnMap.put(ORGANIZATION_ATTRIBUTES_FIELD, VIEW_ATTR_KEY_COLUMN); attributeColumnMap.put(PAGINATION_AFTER, VIEW_CREATED_TIME_COLUMN); attributeColumnMap.put(PAGINATION_BEFORE, VIEW_CREATED_TIME_COLUMN); - attributeColumnMap.put(PAGINATION_AFTER_ATTRIBUTE, VIEW_ATTR_KEY_COLUMN); - attributeColumnMap.put(PAGINATION_BEFORE_ATTRIBUTE, VIEW_ATTR_KEY_COLUMN); } /** @@ -234,10 +231,8 @@ public enum ErrorMessages { "The complex query used for filtering is not supported."), ERROR_CODE_INVALID_PAGINATION_PARAMETER_NEGATIVE_LIMIT("60025", "Invalid pagination parameters.", "'limit' shouldn't be negative."), - ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION("60026", "Unable to retrieve organizations.", "Invalid " + - "cursor used for pagination."), - ERROR_CODE_INVALID_CURSOR_FOR_META_ATTRIBUTE_PAGINATION("60027", "Unable to retrieve " + - "organizations' meta attributes.", "Invalid cursor used for pagination."), + ERROR_CODE_INVALID_CURSOR_FOR_PAGINATION("60026", "Unable to retrieve paginated result.", + "Invalid cursor used for pagination."), ERROR_CODE_UNSUPPORTED_ORGANIZATION_STATUS("60028", "Unsupported status provided.", "Organization status must be 'ACTIVE' or 'DISABLED'."), ERROR_CODE_ACTIVE_CHILD_ORGANIZATIONS_EXIST("60029", "Active child organizations exist.", diff --git a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java index 7c880fe2..0ffab2fc 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.service/src/main/java/org/wso2/carbon/identity/organization/management/service/dao/impl/OrganizationManagementDAOImpl.java @@ -104,8 +104,11 @@ import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.LT; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ORGANIZATION_ATTRIBUTES_FIELD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ORGANIZATION_ATTRIBUTES_FIELD_PREFIX; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ORGANIZATION_CREATED_TIME_FIELD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationStatus.ACTIVE; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.OrganizationStatus.DISABLED; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_AFTER; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PAGINATION_BEFORE; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PARENT_ID_FILTER_PLACEHOLDER_PREFIX; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PATCH_OP_ADD; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.PATCH_OP_REMOVE; @@ -730,7 +733,7 @@ private List getOrganizationsList(boolean authorizedSubOrgsOnly, b String applicationAudience) throws OrganizationManagementServerException { - FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes); + FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes, ORGANIZATION_CREATED_TIME_FIELD); FilterQueryBuilder parentIdFilterQueryBuilder = buildParentIdFilterQuery(parentIdExpressionNodes); String userID = getUserId(); @@ -789,7 +792,7 @@ private List getOrganizationsBasicInfo(boolean authorizedSubO String applicationAudience) throws OrganizationManagementServerException { - FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes); + FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes, ORGANIZATION_CREATED_TIME_FIELD); FilterQueryBuilder parentIdFilterQueryBuilder = buildParentIdFilterQuery(parentIdExpressionNodes); String userID = getUserId(); @@ -980,7 +983,8 @@ private Organization buildOrganizationFromRawData(List expressionNodes, FilterQueryBuilder filterQueryBuilder) + private void appendFilterQuery(List expressionNodes, FilterQueryBuilder filterQueryBuilder, + String attributeUsedForCursor) throws OrganizationManagementServerException { int count = 1; @@ -992,6 +996,10 @@ private void appendFilterQuery(List expressionNodes, FilterQuery String operation = expressionNode.getOperation(); String value = expressionNode.getValue(); String attributeValue = expressionNode.getAttributeValue(); + if (attributeValue.equalsIgnoreCase(PAGINATION_AFTER) || + attributeValue.equalsIgnoreCase(PAGINATION_BEFORE)) { + attributeValue = attributeUsedForCursor; + } String attributeName = ATTRIBUTE_COLUMN_MAP.get(attributeValue); if (attributeValue.startsWith(ORGANIZATION_ATTRIBUTES_FIELD_PREFIX)) { @@ -1344,7 +1352,7 @@ public List getOrganizationsMetaAttributes(boolean recursive, Integer li String sortOrder, List expressionNodes) throws OrganizationManagementServerException { - FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes); + FilterQueryBuilder filterQueryBuilder = buildFilterQuery(expressionNodes, ORGANIZATION_ATTRIBUTES_FIELD); String sqlStmt = getOrgMetaAttributesSqlStmt(recursive, sortOrder, filterQueryBuilder); List organizationMetaAttributes; @@ -1527,11 +1535,11 @@ private boolean isDateTimeAndMSSql(String attributeName) throws OrganizationMana && isMSSqlDB(); } - private FilterQueryBuilder buildFilterQuery(List expressionNodes) + private FilterQueryBuilder buildFilterQuery(List expressionNodes, String attributeUsedForCursor) throws OrganizationManagementServerException { FilterQueryBuilder filterQueryBuilder = new FilterQueryBuilder(); - appendFilterQuery(expressionNodes, filterQueryBuilder); + appendFilterQuery(expressionNodes, filterQueryBuilder, attributeUsedForCursor); return filterQueryBuilder; } From c235ad75fc50b31212641dc4d1412a8c1c93c564 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Mon, 22 Jul 2024 03:58:15 +0000 Subject: [PATCH 10/11] [WSO2 Release] [Jenkins #213] [Release 1.1.11] prepare release v1.1.11 --- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/pom.xml b/components/org.wso2.carbon.identity.organization.management.service/pom.xml index da17f655..482d796e 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.service/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.11-SNAPSHOT + 1.1.11 ../../pom.xml diff --git a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml index 03622f47..ebf77f4b 100644 --- a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.11-SNAPSHOT + 1.1.11 ../../pom.xml diff --git a/pom.xml b/pom.xml index 6610d1e9..242fa8e8 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.11-SNAPSHOT + 1.1.11 4.0.0 pom WSO2 Carbon - Organization Management Core @@ -36,7 +36,7 @@ https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git - HEAD + v1.1.11 From 723ee63d56bbda911a26912307b35c8c1c6b667c Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Mon, 22 Jul 2024 03:58:17 +0000 Subject: [PATCH 11/11] [WSO2 Release] [Jenkins #213] [Release 1.1.11] prepare for next development iteration --- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.service/pom.xml b/components/org.wso2.carbon.identity.organization.management.service/pom.xml index 482d796e..2d521a15 100644 --- a/components/org.wso2.carbon.identity.organization.management.service/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.service/pom.xml @@ -20,7 +20,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.11 + 1.1.12-SNAPSHOT ../../pom.xml diff --git a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml index ebf77f4b..49a79940 100644 --- a/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml +++ b/features/org.wso2.carbon.identity.organization.management.core.server.feature/pom.xml @@ -19,7 +19,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.11 + 1.1.12-SNAPSHOT ../../pom.xml diff --git a/pom.xml b/pom.xml index 242fa8e8..530cfddb 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.wso2.carbon.identity.organization.management.core identity-organization-management-core - 1.1.11 + 1.1.12-SNAPSHOT 4.0.0 pom WSO2 Carbon - Organization Management Core @@ -36,7 +36,7 @@ https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git scm:git:https://github.com/wso2-extensions/identity-organization-management-core.git - v1.1.11 + HEAD