From e6257482de79495de650d0982dc9f642162de9d7 Mon Sep 17 00:00:00 2001 From: Pahansith Date: Fri, 26 Mar 2021 13:34:54 +0530 Subject: [PATCH 1/4] Fix error in unmanaged app uninstall --- .../core/dao/impl/subscription/GenericSubscriptionDAOImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java index 576eec9a6c..2d1a7e5411 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java @@ -941,7 +941,7 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc "ON " + "AP_DEVICE_SUBSCRIPTION.AP_APP_RELEASE_ID = AP_APP_RELEASE.AP_APP_ID " + "WHERE PACKAGE_NAME = ? " + - "AND DM_DEVICE_ID = ?" + + "AND DM_DEVICE_ID = ? " + "AND UNSUBSCRIBED = 'FALSE' " + "AND STATUS = 'COMPLETED';"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { From 4394ceaeed9752a42f68556763071acead4dd035 Mon Sep 17 00:00:00 2001 From: inoshperera Date: Sat, 27 Mar 2021 16:21:06 +0530 Subject: [PATCH 2/4] Add enterprise API tag to allowed tags (cherry picked from commit 4116b7776b277e0e21844300f3618ffb1243e300) --- .../apimgt/application/extension/api/util/APIUtil.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java index 43490e0c83..014a59b9c5 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java @@ -48,6 +48,7 @@ public class APIUtil { private static final String DEFAULT_APP_MGT_SUB_MGT_TAG = "subscription_management"; private static final String DEFAULT_ANALYTICS_ARTIFACT_TAG = "analytics_artifacts_management"; private static final String DEFAULT_TRANSPORT_MGT_TAG = "transport_management"; + private static final String DEFAULT_ENTERPRISE_TAG= "androidforwork"; public static final String PERMISSION_PROPERTY_NAME = "name"; @@ -118,6 +119,11 @@ public class APIUtil { allowedApisTags.add(DEFAULT_APP_MGT_SUB_MGT_TAG); allowedApisTags.add(DEFAULT_ANALYTICS_ARTIFACT_TAG); allowedApisTags.add(DEFAULT_TRANSPORT_MGT_TAG); + // In an environment only super tenant should be capable of calling this API tag + if (PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId() == + MultitenantConstants.SUPER_TENANT_ID) { + allowedApisTags.add(DEFAULT_ENTERPRISE_TAG); + } return allowedApisTags; } From 6a7099f97f949e08d3210e0455b336d2c1e86dc2 Mon Sep 17 00:00:00 2001 From: Farheen Boosary Date: Mon, 29 Mar 2021 07:49:47 +0000 Subject: [PATCH 3/4] Handle execution of queries contain IN clause with empty array (cherry picked from commit 0f39b2f2536a4c65f15cedb9ac1f767c09ce656d) --- .../GenericApplicationDAOImpl.java | 14 ++++++-- .../GenericApplicationReleaseDAOImpl.java | 6 +++- .../dao/impl/review/GenericReviewDAOImpl.java | 14 +++++++- .../dao/impl/review/OracleReviewDAOImpl.java | 11 +++++- .../impl/review/SQLServerReviewDAOImpl.java | 11 +++++- .../GenericSubscriptionDAOImpl.java | 36 ++++++++++++++----- .../core/dao/impl/AbstractDeviceDAOImpl.java | 17 +++++++++ .../core/dao/impl/AbstractEventConfigDAO.java | 15 ++++++++ .../core/dao/impl/AbstractGroupDAOImpl.java | 3 ++ .../mgt/core/dao/impl/GeofenceDAOImpl.java | 6 ++++ .../dao/impl/device/GenericDeviceDAOImpl.java | 8 ++++- .../dao/impl/device/OracleDeviceDAOImpl.java | 8 ++++- .../impl/device/PostgreSQLDeviceDAOImpl.java | 8 ++++- .../impl/device/SQLServerDeviceDAOImpl.java | 8 ++++- 14 files changed, 146 insertions(+), 19 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java index 845c4626d5..a4d9d4a87a 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java @@ -24,6 +24,7 @@ import org.wso2.carbon.device.application.mgt.common.AppLifecycleState; import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO; import org.wso2.carbon.device.application.mgt.common.dto.CategoryDTO; import org.wso2.carbon.device.application.mgt.common.Filter; +import org.wso2.carbon.device.application.mgt.common.dto.ReviewDTO; import org.wso2.carbon.device.application.mgt.common.dto.TagDTO; import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO; @@ -491,6 +492,9 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic + " from the database"); } try { + if (packageNames.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); int index = 1; StringJoiner joiner = new StringJoiner(",", @@ -826,9 +830,12 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic log.debug("Request received in DAO Layer to get category ids for given category names"); } try { + List tagIds = new ArrayList<>(); + if (categoryNames.isEmpty()) { + return tagIds; + } Connection conn = this.getDBConnection(); int index = 1; - List tagIds = new ArrayList<>(); StringJoiner joiner = new StringJoiner(",", "SELECT AP_APP_CATEGORY.ID AS ID FROM AP_APP_CATEGORY WHERE AP_APP_CATEGORY.CATEGORY IN (", ") AND TENANT_ID = ?"); @@ -1117,9 +1124,12 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic log.debug("Request received in DAO Layer to get tag ids for given tag names"); } try { + List tagIds = new ArrayList<>(); + if (tagNames.isEmpty()) { + return tagIds; + } Connection conn = this.getDBConnection(); int index = 1; - List tagIds = new ArrayList<>(); StringJoiner joiner = new StringJoiner(",", "SELECT AP_APP_TAG.ID AS ID FROM AP_APP_TAG WHERE AP_APP_TAG.TAG IN (", ") AND TENANT_ID = ?"); diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java index ffe45ba3d3..c03ab8bea2 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java @@ -564,6 +564,11 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements public List getReleaseByPackages(List packages, int tenantId) throws ApplicationManagementDAOException { + List releaseDTOs = new ArrayList<>(); + if (packages.isEmpty()) { + return releaseDTOs; + } + String sql = "SELECT " + "AR.ID AS RELEASE_ID, " + "AR.DESCRIPTION AS RELEASE_DESCRIPTION, " @@ -600,7 +605,6 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements } statement.setInt(index, tenantId); try (ResultSet resultSet = statement.executeQuery()) { - List releaseDTOs = new ArrayList<>(); while (resultSet.next()) { releaseDTOs.add(DAOUtil.constructAppReleaseDTO(resultSet)); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/GenericReviewDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/GenericReviewDAOImpl.java index a727c52359..24052730b3 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/GenericReviewDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/GenericReviewDAOImpl.java @@ -110,6 +110,9 @@ public class GenericReviewDAOImpl extends AbstractDAOImpl implements ReviewDAO { + "application. Commenting user: " + username + " and tenant-id: " + tenantId); } try { + if (appReleaseIds.isEmpty()) { + return false; + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT rv.ID FROM AP_APP_REVIEW rv WHERE rv.AP_APP_RELEASE_ID IN (", @@ -283,6 +286,9 @@ public class GenericReviewDAOImpl extends AbstractDAOImpl implements ReviewDAO { log.debug("DAO request is received to Get all active application reviews."); } try { + if (releaseIds.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT " + "AP_APP_REVIEW.ID AS ID, " @@ -336,6 +342,9 @@ public class GenericReviewDAOImpl extends AbstractDAOImpl implements ReviewDAO { log.debug("DAO request is received to Get all active application reviews of user " + username); } try { + if (releaseIds.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT " @@ -473,6 +482,10 @@ public class GenericReviewDAOImpl extends AbstractDAOImpl implements ReviewDAO { log.debug("DAO request is received to Get all application rating values of an application."); } try { + List reviews = new ArrayList<>(); + if (uuids.isEmpty()) { + return reviews; + } int index = 1; Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", @@ -487,7 +500,6 @@ public class GenericReviewDAOImpl extends AbstractDAOImpl implements ReviewDAO { } ps.setInt(index, tenantId); try (ResultSet rs = ps.executeQuery()) { - List reviews = new ArrayList<>(); while (rs.next()) { reviews.add(rs.getInt("RATING")); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/OracleReviewDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/OracleReviewDAOImpl.java index 2231560930..ac252e52f7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/OracleReviewDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/OracleReviewDAOImpl.java @@ -97,6 +97,9 @@ public class OracleReviewDAOImpl extends GenericReviewDAOImpl { log.debug("DAO request is received to Get all active application reviews."); } try { + if (releaseIds.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT " + "AP_APP_REVIEW.ID AS ID, " @@ -150,6 +153,9 @@ public class OracleReviewDAOImpl extends GenericReviewDAOImpl { log.debug("DAO request is received to Get all active application reviews of user " + username); } try { + if (releaseIds.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT " @@ -203,6 +209,10 @@ public class OracleReviewDAOImpl extends GenericReviewDAOImpl { log.debug("DAO request is received to Get all application rating values of an application."); } try { + List reviews = new ArrayList<>(); + if (uuids.isEmpty()) { + return reviews; + } int index = 1; Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", @@ -217,7 +227,6 @@ public class OracleReviewDAOImpl extends GenericReviewDAOImpl { } ps.setInt(index, tenantId); try (ResultSet rs = ps.executeQuery()) { - List reviews = new ArrayList<>(); while (rs.next()) { reviews.add(rs.getInt("RATING")); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/SQLServerReviewDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/SQLServerReviewDAOImpl.java index d169a6190a..213d619b0c 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/SQLServerReviewDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/review/SQLServerReviewDAOImpl.java @@ -97,6 +97,9 @@ public class SQLServerReviewDAOImpl extends GenericReviewDAOImpl { log.debug("DAO request is received to Get all active application reviews."); } try { + if (releaseIds.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT " + "AP_APP_REVIEW.ID AS ID, " @@ -150,6 +153,9 @@ public class SQLServerReviewDAOImpl extends GenericReviewDAOImpl { log.debug("DAO request is received to Get all active application reviews of user " + username); } try { + if (releaseIds.isEmpty()) { + return new ArrayList<>(); + } Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", "SELECT " @@ -203,6 +209,10 @@ public class SQLServerReviewDAOImpl extends GenericReviewDAOImpl { log.debug("DAO request is received to Get all application rating values of an application."); } try { + List reviews = new ArrayList<>(); + if (uuids.isEmpty()) { + return reviews; + } int index = 1; Connection conn = this.getDBConnection(); StringJoiner joiner = new StringJoiner(",", @@ -217,7 +227,6 @@ public class SQLServerReviewDAOImpl extends GenericReviewDAOImpl { } ps.setInt(index, tenantId); try (ResultSet rs = ps.executeQuery()) { - List reviews = new ArrayList<>(); while (rs.next()) { reviews.add(rs.getInt("RATING")); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java index 2d1a7e5411..c2f559e96b 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java @@ -383,9 +383,12 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc log.debug("Request received in DAO Layer to get device subscriptions for given device ids."); } try { + Map deviceSubscriptionDTOHashMap = new HashMap<>(); + if (deviceIds.isEmpty()) { + return deviceSubscriptionDTOHashMap; + } Connection conn = this.getDBConnection(); int index = 1; - Map deviceSubscriptionDTOHashMap = new HashMap<>(); StringJoiner joiner = new StringJoiner(",", "SELECT " + "DS.ID AS ID, " @@ -439,9 +442,12 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc log.debug("Request received in DAO Layer to get already subscribed users for given list of user names."); } try { + List subscribedUsers = new ArrayList<>(); + if (users.isEmpty()) { + return subscribedUsers; + } Connection conn = this.getDBConnection(); int index = 1; - List subscribedUsers = new ArrayList<>(); StringJoiner joiner = new StringJoiner(",", "SELECT US.USER_NAME AS USER_NAME " + "FROM AP_USER_SUBSCRIPTION US " @@ -479,9 +485,12 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc log.debug("Request received in DAO Layer to get already subscribed role names for given list of roles."); } try { + List subscribedRoles = new ArrayList<>(); + if (roles.isEmpty()) { + return subscribedRoles; + } Connection conn = this.getDBConnection(); int index = 1; - List subscribedUsers = new ArrayList<>(); StringJoiner joiner = new StringJoiner(",", "SELECT RS.ROLE_NAME AS ROLE " + "FROM AP_ROLE_SUBSCRIPTION RS " @@ -496,11 +505,11 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc ps.setInt(index, tenantId); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { - subscribedUsers.add(rs.getString("ROLE")); + subscribedRoles.add(rs.getString("ROLE")); } } } - return subscribedUsers; + return subscribedRoles; } catch (DBConnectionException e) { String msg = "Error occurred while obtaining the DB connection to getg subscribed roles for given role " + "names."; @@ -520,9 +529,12 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc log.debug("Request received in DAO Layer to get already subscribed groups for given list of groups."); } try { + List subscribedGroups = new ArrayList<>(); + if (groups.isEmpty()) { + return subscribedGroups; + } Connection conn = this.getDBConnection(); int index = 1; - List subscribedUsers = new ArrayList<>(); StringJoiner joiner = new StringJoiner(",", "SELECT GS.GROUP_NAME AS GROUP_NAME " + "FROM AP_GROUP_SUBSCRIPTION GS " @@ -537,11 +549,11 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc ps.setInt(index, tenantId); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { - subscribedUsers.add(rs.getString("GROUP_NAME")); + subscribedGroups.add(rs.getString("GROUP_NAME")); } } } - return subscribedUsers; + return subscribedGroups; } catch (DBConnectionException e) { String msg = "Error occurred while obtaining the DB connection to get already subscribed groups for given " + "group names."; @@ -562,9 +574,12 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc log.debug("Request received to DAO Layer to get already subscribed dvice Ids for given list of device Ids."); } try { + List subscribedDevices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return subscribedDevices; + } Connection conn = this.getDBConnection(); int index = 1; - List subscribedDevices = new ArrayList<>(); StringJoiner joiner = new StringJoiner(",", "SELECT DS.ID AS DEVICE_SUBSCRIPTION_ID " + "FROM AP_DEVICE_SUBSCRIPTION DS " @@ -695,6 +710,9 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc public boolean updateDeviceSubStatus(int deviceId, List deviceSubIds, String status, int tenantId) throws ApplicationManagementDAOException { try { + if (deviceSubIds.isEmpty()) { + return false; + } Connection conn = this.getDBConnection(); int index = 1; StringJoiner joiner = new StringJoiner(",", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index a7d7029c0f..749a31e0bb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -380,6 +380,9 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { PreparedStatement stmt = null; ResultSet resultSet = null; List devices = new ArrayList<>(); + if (deviceProps.isEmpty()) { + return devices; + } try { List> outputLists = new ArrayList<>(); List deviceList = null; @@ -935,6 +938,9 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { throws DeviceManagementDAOException { List devices = new ArrayList<>(); try { + if (deviceStatuses.isEmpty()) { + return devices; + } Connection conn = this.getConnection(); StringJoiner joiner = new StringJoiner(",","SELECT " + "e1.OWNER, " @@ -1222,6 +1228,9 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { Connection conn; PreparedStatement stmt = null; try { + if (devices.isEmpty()) { + return false; + } conn = this.getConnection(); StringBuilder sql = new StringBuilder("UPDATE DM_ENROLMENT SET STATUS = ? WHERE DEVICE_ID IN " + "(SELECT d.ID FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.DEVICE_TYPE_ID = t.ID AND d.DEVICE_IDENTIFICATION IN ("); @@ -1913,6 +1922,10 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { int counter = 0; List devices = new ArrayList<>(); + if (deviceIdentifiers.isEmpty()) { + return devices; + } + StringJoiner joiner = new StringJoiner(",", "SELECT " + "d1.ID AS DEVICE_ID, d1.DESCRIPTION, d1.NAME AS DEVICE_NAME, d1.DEVICE_TYPE, " @@ -1961,6 +1974,10 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { int counter = 0; List devices = new ArrayList<>(); + if (deviceIdentifiers.isEmpty() || statuses.isEmpty()) { + return devices; + } + StringJoiner statusJoiner = new StringJoiner(",", "e.STATUS IN (", ") "); while (counter < statuses.size()) { statusJoiner.add("?"); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java index 43609ed020..a0cc3889a0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEventConfigDAO.java @@ -68,6 +68,9 @@ public abstract class AbstractEventConfigDAO implements EventConfigDAO { public List getEventsOfGroups(List groupIds, int tenantId) throws EventManagementDAOException { try { List eventList = new ArrayList<>(); + if (groupIds.isEmpty()) { + return eventList; + } Connection conn = this.getConnection(); String sql = "SELECT " + "E.ID AS EVENT_ID, " + @@ -145,6 +148,9 @@ public abstract class AbstractEventConfigDAO implements EventConfigDAO { @Override public void deleteEventGroupMappingRecordsByEventIds(List eventsIdsToDelete) throws EventManagementDAOException { try { + if (eventsIdsToDelete.isEmpty()) { + return; + } Connection conn = this.getConnection(); String sql = "DELETE FROM DM_DEVICE_EVENT_GROUP_MAPPING WHERE EVENT_ID IN (%s)"; String inClause = String.join(", ", Collections.nCopies(eventsIdsToDelete.size(), "?")); @@ -166,6 +172,9 @@ public abstract class AbstractEventConfigDAO implements EventConfigDAO { @Override public void deleteEventGroupMappingRecordsByGroupIds(List groupIdsToDelete) throws EventManagementDAOException { try { + if (groupIdsToDelete.isEmpty()) { + return; + } Connection conn = this.getConnection(); String sql = "DELETE FROM DM_DEVICE_EVENT_GROUP_MAPPING WHERE GROUP_ID IN (%s)"; String inClause = String.join(", ", Collections.nCopies(groupIdsToDelete.size(), "?")); @@ -230,6 +239,9 @@ public abstract class AbstractEventConfigDAO implements EventConfigDAO { public List getEventsById(List eventIdList) throws EventManagementDAOException { try { List eventList = new ArrayList<>(); + if (eventIdList.isEmpty()) { + return eventList; + } Connection conn = this.getConnection(); String sql = "SELECT " + "ID AS EVENT_ID, " + @@ -269,6 +281,9 @@ public abstract class AbstractEventConfigDAO implements EventConfigDAO { public List getGroupsOfEvents(List eventIdList) throws EventManagementDAOException { try { List groupIdList = new ArrayList<>(); + if (eventIdList.isEmpty()) { + return groupIdList; + } Connection conn = this.getConnection(); String sql = "SELECT " + "GROUP_ID " + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java index 11e00c9f33..04d4bce584 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java @@ -772,6 +772,9 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { throws GroupManagementDAOException { List devices = new ArrayList<>(); try { + if (deviceStatuses.isEmpty()) { + return devices; + } Connection conn = GroupManagementDAOFactory.getConnection(); StringJoiner joiner = new StringJoiner(",","SELECT " + "d1.DEVICE_ID, " diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java index 5026434695..e0d1efa4d1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java @@ -421,6 +421,9 @@ public class GeofenceDAOImpl implements GeofenceDAO { public Map> getEventsOfGeoFences(List geofenceIds) throws DeviceManagementDAOException { try { Map> geoFenceEventMap = new HashMap<>(); + if (geofenceIds.isEmpty()) { + return geoFenceEventMap; + } Connection conn = this.getConnection(); String sql = "SELECT " + "E.ID AS EVENT_ID, " + @@ -490,6 +493,9 @@ public class GeofenceDAOImpl implements GeofenceDAO { public Set getGroupIdsOfGeoFences(List fenceIds) throws DeviceManagementDAOException { try { Set geoFenceGroupSet = new HashSet<>(); + if (fenceIds.isEmpty()) { + return geoFenceGroupSet; + } Connection conn = this.getConnection(); String sql = "SELECT " + "FENCE_ID, " + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java index 07a2882b3d..83615eb056 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java @@ -883,6 +883,10 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { Connection conn; try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } conn = this.getConnection(); int index = 1; @@ -937,7 +941,6 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setInt(index, limitValue); try (ResultSet rs = ps.executeQuery()) { - List devices = new ArrayList<>(); while (rs.next()) { devices.add(DeviceManagementDAOUtil.loadDevice(rs)); } @@ -956,6 +959,9 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { public int getSubscribedDeviceCount(List deviceIds, int tenantId, List status) throws DeviceManagementDAOException { try { + if (deviceIds.isEmpty()) { + return 0; + } Connection conn = this.getConnection(); int index = 1; StringJoiner joiner = new StringJoiner(",", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index b143136ef9..ed5a8c843c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -853,6 +853,10 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { Connection conn; try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } conn = this.getConnection(); int index = 1; @@ -907,7 +911,6 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setInt(index, limitValue); try (ResultSet rs = ps.executeQuery()) { - List devices = new ArrayList<>(); while (rs.next()) { devices.add(DeviceManagementDAOUtil.loadDevice(rs)); } @@ -926,6 +929,9 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { public int getSubscribedDeviceCount(List deviceIds, int tenantId, List status) throws DeviceManagementDAOException { try { + if (deviceIds.isEmpty()) { + return 0; + } Connection conn = this.getConnection(); int index = 1; StringJoiner joiner = new StringJoiner(",", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java index 4a7560f9f3..cfefbb8b3f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java @@ -833,6 +833,10 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { Connection conn; try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } conn = this.getConnection(); int index = 1; @@ -887,7 +891,6 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setInt(index, limitValue); try (ResultSet rs = ps.executeQuery()) { - List devices = new ArrayList<>(); while (rs.next()) { devices.add(DeviceManagementDAOUtil.loadDevice(rs)); } @@ -906,6 +909,9 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { public int getSubscribedDeviceCount(List deviceIds, int tenantId, List status) throws DeviceManagementDAOException { try { + if (deviceIds.isEmpty()) { + return 0; + } Connection conn = this.getConnection(); int index = 1; StringJoiner joiner = new StringJoiner(",", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 11112c4655..755f882a46 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -699,6 +699,10 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { Connection conn; try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } conn = this.getConnection(); int index = 1; @@ -753,7 +757,6 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setInt(index, limitValue); try (ResultSet rs = ps.executeQuery()) { - List devices = new ArrayList<>(); while (rs.next()) { devices.add(DeviceManagementDAOUtil.loadDevice(rs)); } @@ -1039,6 +1042,9 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { public int getSubscribedDeviceCount(List deviceIds, int tenantId, List status) throws DeviceManagementDAOException { try { + if (deviceIds.isEmpty()) { + return 0; + } Connection conn = this.getConnection(); int index = 1; StringJoiner joiner = new StringJoiner(",", From 143d62efd54e14faa40cb437e6508c3525cf8561 Mon Sep 17 00:00:00 2001 From: vigneshan Date: Thu, 1 Apr 2021 11:30:35 +0530 Subject: [PATCH 4/4] Add login cache for sso and non-sso flow (cherry picked from commit 872299a617ccc2a872fd0225e8261262d5f6fe58) --- .../ui/request/interceptor/LoginHandler.java | 155 +++++++++++------- .../request/interceptor/SsoLoginHandler.java | 146 ++++++++++++----- .../interceptor/cache/LoginCacheManager.java | 63 +++++++ .../request/interceptor/cache/OAuthApp.java | 79 +++++++++ .../interceptor/cache/OAuthAppCacheKey.java | 74 +++++++++ .../interceptor/util/HandlerConstants.java | 1 + 6 files changed, 416 insertions(+), 102 deletions(-) create mode 100644 components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/LoginCacheManager.java create mode 100644 components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthApp.java create mode 100644 components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthAppCacheKey.java diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java index 133681355b..1a98cef5a9 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java @@ -24,6 +24,9 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import io.entgra.ui.request.interceptor.beans.AuthData; +import io.entgra.ui.request.interceptor.cache.LoginCacheManager; +import io.entgra.ui.request.interceptor.cache.OAuthApp; +import io.entgra.ui.request.interceptor.cache.OAuthAppCacheKey; import io.entgra.ui.request.interceptor.exceptions.LoginException; import io.entgra.ui.request.interceptor.util.HandlerConstants; import io.entgra.ui.request.interceptor.util.HandlerUtil; @@ -74,26 +77,61 @@ public class LoginHandler extends HttpServlet { JsonArray tags = uiConfigJsonObject.get("appRegistration").getAsJsonObject().get("tags").getAsJsonArray(); JsonArray scopes = uiConfigJsonObject.get("scopes").getAsJsonArray(); - HttpPost apiRegEndpoint = new HttpPost(gatewayUrl + HandlerConstants.APP_REG_ENDPOINT); - apiRegEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + Base64.getEncoder() - .encodeToString((username + HandlerConstants.COLON + password).getBytes())); - apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); - apiRegEndpoint.setEntity(HandlerUtil.constructAppRegPayload(tags, HandlerConstants.PUBLISHER_APPLICATION_NAME, username, password)); + // Check if OAuth app cache exists. If not create a new application. + LoginCacheManager loginCacheManager = new LoginCacheManager(); + loginCacheManager.initializeCacheManager(); + OAuthAppCacheKey oAuthAppCacheKey = new OAuthAppCacheKey(HandlerConstants.PUBLISHER_APPLICATION_NAME, username); + OAuthApp oAuthApp = loginCacheManager.getOAuthAppCache(oAuthAppCacheKey); - ProxyResponse clientAppResponse = HandlerUtil.execute(apiRegEndpoint); + if (oAuthApp == null) { + HttpPost apiRegEndpoint = new HttpPost(gatewayUrl + HandlerConstants.APP_REG_ENDPOINT); + apiRegEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + Base64.getEncoder() + .encodeToString((username + HandlerConstants.COLON + password).getBytes())); + apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); + apiRegEndpoint.setEntity(HandlerUtil.constructAppRegPayload(tags, HandlerConstants.PUBLISHER_APPLICATION_NAME, username, password)); - if (clientAppResponse.getCode() == HttpStatus.SC_UNAUTHORIZED) { - HandlerUtil.handleError(resp, clientAppResponse); - return; - } - if (clientAppResponse.getCode() == HttpStatus.SC_CREATED && getTokenAndPersistInSession(req, resp, - clientAppResponse.getData(), scopes)) { - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_OK); - HandlerUtil.handleSuccess(resp, proxyResponse); - return; + ProxyResponse clientAppResponse = HandlerUtil.execute(apiRegEndpoint); + + if (clientAppResponse.getCode() == HttpStatus.SC_UNAUTHORIZED) { + HandlerUtil.handleError(resp, clientAppResponse); + return; + } + + if (clientAppResponse.getCode() == HttpStatus.SC_CREATED) { + JsonParser jsonParser = new JsonParser(); + JsonElement jClientAppResult = jsonParser.parse(clientAppResponse.getData()); + String clientId = null; + String clientSecret = null; + String encodedClientApp = null; + if (jClientAppResult.isJsonObject()) { + JsonObject jClientAppResultAsJsonObject = jClientAppResult.getAsJsonObject(); + clientId = jClientAppResultAsJsonObject.get("client_id").getAsString(); + clientSecret = jClientAppResultAsJsonObject.get("client_secret").getAsString(); + encodedClientApp = Base64.getEncoder() + .encodeToString((clientId + HandlerConstants.COLON + clientSecret).getBytes()); + + oAuthAppCacheKey = new OAuthAppCacheKey(HandlerConstants.PUBLISHER_APPLICATION_NAME, username); + oAuthApp = new OAuthApp( + HandlerConstants.PUBLISHER_APPLICATION_NAME, + username, + clientId, + clientSecret, + encodedClientApp + ); + loginCacheManager.addOAuthAppToCache(oAuthAppCacheKey, oAuthApp); + } + + if (getTokenAndPersistInSession(req, resp, clientId, clientSecret, encodedClientApp, scopes)) { + ProxyResponse proxyResponse = new ProxyResponse(); + proxyResponse.setCode(HttpStatus.SC_OK); + HandlerUtil.handleSuccess(resp, proxyResponse); + return; + } + } + HandlerUtil.handleError(resp, null); + } else { + getTokenAndPersistInSession(req, resp, oAuthApp.getClientId(), oAuthApp.getClientSecret(), oAuthApp.getEncodedClientApp(), scopes); } - HandlerUtil.handleError(resp, null); } catch (IOException e) { log.error("Error occurred while sending the response into the socket. ", e); } catch (JsonSyntaxException e) { @@ -103,57 +141,54 @@ public class LoginHandler extends HttpServlet { } } - /*** + /** * Generates token from token endpoint and persists them inside the session * - * @param req - {@link HttpServletRequest} - * @param clientAppResult - clientAppResult - * @param scopes - scopes defied in the application-mgt.xml - * @throws LoginException - login exception throws when getting token result + * @param req - {@link HttpServletRequest} + * @param resp - {@link HttpServletResponse} + * @param clientId - clientId of the OAuth app + * @param clientSecret - clientSecret of the OAuth app + * @param encodedClientApp - Base64 encoded clientId:clientSecret. + * @param scopes - User scopes JSON Array + * @return boolean response + * @throws LoginException - Throws if any error occurs while getting login response */ private boolean getTokenAndPersistInSession(HttpServletRequest req, HttpServletResponse resp, - String clientAppResult, JsonArray scopes) throws LoginException { + String clientId, String clientSecret, String encodedClientApp, + JsonArray scopes) throws LoginException { JsonParser jsonParser = new JsonParser(); try { - JsonElement jClientAppResult = jsonParser.parse(clientAppResult); - if (jClientAppResult.isJsonObject()) { - JsonObject jClientAppResultAsJsonObject = jClientAppResult.getAsJsonObject(); - String clientId = jClientAppResultAsJsonObject.get("client_id").getAsString(); - String clientSecret = jClientAppResultAsJsonObject.get("client_secret").getAsString(); - String encodedClientApp = Base64.getEncoder() - .encodeToString((clientId + HandlerConstants.COLON + clientSecret).getBytes()); - - ProxyResponse tokenResultResponse = getTokenResult(encodedClientApp, scopes); - - if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { - log.error("Error occurred while invoking the API to get token data."); - HandlerUtil.handleError(resp, tokenResultResponse); - return false; - } - String tokenResult = tokenResultResponse.getData(); - if (tokenResult == null) { - log.error("Invalid token response is received."); - HandlerUtil.handleError(resp, tokenResultResponse); - return false; - } - JsonElement jTokenResult = jsonParser.parse(tokenResult); - if (jTokenResult.isJsonObject()) { - JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject(); - HttpSession session = req.getSession(false); - if (session == null) { - return false; - } - AuthData authData = new AuthData(); - authData.setClientId(clientId); - authData.setClientSecret(clientSecret); - authData.setEncodedClientApp(encodedClientApp); - authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); - authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); - authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); - session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData); - return true; + ProxyResponse tokenResultResponse = getTokenResult(encodedClientApp, scopes); + + if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { + log.error("Error occurred while invoking the API to get token data."); + HandlerUtil.handleError(resp, tokenResultResponse); + return false; + } + String tokenResult = tokenResultResponse.getData(); + if (tokenResult == null) { + log.error("Invalid token response is received."); + HandlerUtil.handleError(resp, tokenResultResponse); + return false; + } + + JsonElement jTokenResult = jsonParser.parse(tokenResult); + if (jTokenResult.isJsonObject()) { + JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject(); + HttpSession session = req.getSession(false); + if (session == null) { + return false; } + AuthData authData = new AuthData(); + authData.setClientId(clientId); + authData.setClientSecret(clientSecret); + authData.setEncodedClientApp(encodedClientApp); + authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); + authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); + authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); + session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData); + return true; } return false; } catch (IOException e) { diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java index 1ade046d43..872fd189d1 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java @@ -23,6 +23,9 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; +import io.entgra.ui.request.interceptor.cache.LoginCacheManager; +import io.entgra.ui.request.interceptor.cache.OAuthApp; +import io.entgra.ui.request.interceptor.cache.OAuthAppCacheKey; import io.entgra.ui.request.interceptor.util.HandlerConstants; import io.entgra.ui.request.interceptor.util.HandlerUtil; import org.apache.commons.lang.text.StrSubstitutor; @@ -72,24 +75,62 @@ public class SsoLoginHandler extends HttpServlet { private static String encodedAdminCredentials; private static String encodedClientApp; private static String applicationId; + private static String applicationName; private static String baseContextPath; private JsonObject uiConfigJsonObject; private HttpSession httpSession; + private LoginCacheManager loginCacheManager; + private OAuthApp oAuthApp; + @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - dynamicClientRegistration(req, resp); - String clientId = httpSession.getAttribute("clientId").toString(); - JsonArray scopesSsoJson = uiConfigJsonObject.get("scopes").getAsJsonArray(); - String scopesSsoString = HandlerUtil.getScopeString(scopesSsoJson); - String loginCallbackUrl = iotsCoreUrl + baseContextPath + HandlerConstants.SSO_LOGIN_CALLBACK; - resp.sendRedirect(iotsCoreUrl + HandlerConstants.AUTHORIZATION_ENDPOINT + - "?response_type=code" + - "&client_id=" + clientId + - "&state=" + - "&scope=openid " + scopesSsoString + - "&redirect_uri=" + loginCallbackUrl); + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + try { + httpSession = req.getSession(false); + + if (httpSession != null) { + httpSession.invalidate(); + } + + httpSession = req.getSession(true); + initializeAdminCredentials(); + baseContextPath = req.getContextPath(); + applicationName = baseContextPath.substring(1, baseContextPath.indexOf("-ui-request-handler")); + + // Check if oauth app cache is available + loginCacheManager = new LoginCacheManager(); + loginCacheManager.initializeCacheManager(); + oAuthApp = loginCacheManager.getOAuthAppCache( + new OAuthAppCacheKey(applicationName, adminUsername) + ); + + if (oAuthApp == null) { + dynamicClientRegistration(req, resp); + } + + String clientId = oAuthApp.getClientId(); + JsonArray scopesSsoJson = uiConfigJsonObject.get("scopes").getAsJsonArray(); + String scopesSsoString = HandlerUtil.getScopeString(scopesSsoJson); + String loginCallbackUrl = iotsCoreUrl + baseContextPath + HandlerConstants.SSO_LOGIN_CALLBACK; + persistAuthSessionData(req, oAuthApp.getClientId(), oAuthApp.getClientSecret(), + oAuthApp.getEncodedClientApp(), scopesSsoString); + + resp.sendRedirect(iotsCoreUrl + HandlerConstants.AUTHORIZATION_ENDPOINT + + "?response_type=code" + + "&client_id=" + clientId + + "&state=" + + "&scope=openid " + scopesSsoString + + "&redirect_uri=" + loginCallbackUrl); + } catch (IOException e) { + log.error("Error occurred while sending the response into the socket. ", e); + } catch (JsonSyntaxException e) { + log.error("Error occurred while parsing the response. ", e); + } catch (ParserConfigurationException e) { + log.error("Error while creating the document builder."); + } catch (SAXException e) { + log.error("Error while parsing xml file.", e); + } } /*** @@ -101,17 +142,6 @@ public class SsoLoginHandler extends HttpServlet { */ private void dynamicClientRegistration(HttpServletRequest req, HttpServletResponse resp) { try { - File userMgtConf = new File("conf/user-mgt.xml"); - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(userMgtConf); - - adminUsername = doc.getElementsByTagName("UserName").item(0).getTextContent(); - adminPassword = doc.getElementsByTagName("Password").item(0).getTextContent(); - - baseContextPath = req.getContextPath(); - String applicationName = baseContextPath.substring(1, baseContextPath.indexOf("-ui-request-handler")); - String iotsCorePort = System.getProperty("iot.core.https.port"); if (HandlerConstants.HTTP_PROTOCOL.equals(req.getScheme())) { @@ -124,14 +154,7 @@ public class SsoLoginHandler extends HttpServlet { + HandlerConstants.COLON + iotsCorePort; String uiConfigUrl = iotsCoreUrl + HandlerConstants.UI_CONFIG_ENDPOINT; - httpSession = req.getSession(false); - if (httpSession != null) { - httpSession.invalidate(); - } - - httpSession = req.getSession(true); uiConfigJsonObject = HandlerUtil.getUIConfigAndPersistInSession(uiConfigUrl, gatewayUrl, httpSession, resp); - JsonArray tags = uiConfigJsonObject.get("appRegistration").getAsJsonObject().get("tags").getAsJsonArray(); JsonArray scopes = uiConfigJsonObject.get("scopes").getAsJsonArray(); @@ -153,19 +176,22 @@ public class SsoLoginHandler extends HttpServlet { if (clientAppResponse.getCode() == HttpStatus.SC_CREATED) { JsonParser jsonParser = new JsonParser(); JsonElement jClientAppResult = jsonParser.parse(clientAppResponse.getData()); + String clientId = null; + String clientSecret = null; + if (jClientAppResult.isJsonObject()) { JsonObject jClientAppResultAsJsonObject = jClientAppResult.getAsJsonObject(); - String clientId = jClientAppResultAsJsonObject.get("client_id").getAsString(); - String clientSecret = jClientAppResultAsJsonObject.get("client_secret").getAsString(); + clientId = jClientAppResultAsJsonObject.get("client_id").getAsString(); + clientSecret = jClientAppResultAsJsonObject.get("client_secret").getAsString(); encodedClientApp = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes()); - String redirectUrl = req.getParameter("redirect"); - httpSession = req.getSession(false); - httpSession.setAttribute("clientId", clientId); - httpSession.setAttribute("clientSecret", clientSecret); - httpSession.setAttribute("encodedClientApp", encodedClientApp); - httpSession.setAttribute("scope", HandlerUtil.getScopeString(scopes)); - httpSession.setAttribute("redirectUrl", redirectUrl); + String scopesString = HandlerUtil.getScopeString(scopes); + persistAuthSessionData(req, clientId, clientSecret, encodedClientApp, scopesString); } + + // cache the oauth app credentials + OAuthAppCacheKey oAuthAppCacheKey = new OAuthAppCacheKey(applicationName, adminUsername); + oAuthApp = new OAuthApp(applicationName, adminUsername, clientId, clientSecret, encodedClientApp); + loginCacheManager.addOAuthAppToCache(oAuthAppCacheKey, oAuthApp); } // Get the details of the registered application @@ -221,7 +247,6 @@ public class SsoLoginHandler extends HttpServlet { if (updateApplicationGrantTypesEndpointResponse.getCode() == HttpStatus.SC_OK) { return; } - HandlerUtil.handleError(resp, null); } catch (IOException e) { log.error("Error occurred while sending the response into the socket. ", e); @@ -229,11 +254,48 @@ public class SsoLoginHandler extends HttpServlet { log.error("Error occurred while parsing the response. ", e); } catch (ParserConfigurationException e) { log.error("Error while creating the document builder."); - } catch ( SAXException e) { + } catch (SAXException e) { log.error("Error while parsing xml file.", e); } } + /** + * Initialize the admin credential variables + * + * @throws ParserConfigurationException - Throws when error occur during initializing the document builder + * @throws IOException - Throws when error occur during document parsing + * @throws SAXException - Throws when error occur during document parsing + */ + private void initializeAdminCredentials() throws ParserConfigurationException, IOException, SAXException { + File userMgtConf = new File("conf/user-mgt.xml"); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(userMgtConf); + + adminUsername = doc.getElementsByTagName("UserName").item(0).getTextContent(); + adminPassword = doc.getElementsByTagName("Password").item(0).getTextContent(); + } + + + /** + * Persist the Auth data inside the session + * + * @param req - Http Servlet request + * @param clientId - Client ID of the SP + * @param clientSecret - Client secret of the SP + * @param encodedClientApp - Base64 encoded clientId:clientSecret. + * @param scopes - User scopes + */ + private void persistAuthSessionData(HttpServletRequest req, String clientId, String clientSecret, + String encodedClientApp, String scopes) { + httpSession = req.getSession(false); + httpSession.setAttribute("clientId", clientId); + httpSession.setAttribute("clientSecret", clientSecret); + httpSession.setAttribute("encodedClientApp", encodedClientApp); + httpSession.setAttribute("scope", scopes); + httpSession.setAttribute("redirectUrl", req.getParameter("redirect")); + } + /*** * Generates payload for application grant_type update payload * @@ -311,7 +373,7 @@ public class SsoLoginHandler extends HttpServlet { */ private void updateSaasApp(String appName) throws ParserConfigurationException, IOException, SAXException { File getAppRequestXmlFile = new File(HandlerConstants.PAYLOADS_DIR + "/get-app-request.xml"); - String identityAppMgtUrl = iotsCoreUrl + HandlerConstants.IDENTITY_APP_MGT_ENDPOINT;; + String identityAppMgtUrl = iotsCoreUrl + HandlerConstants.IDENTITY_APP_MGT_ENDPOINT; HttpPost getApplicationEndpoint = new HttpPost(identityAppMgtUrl); getApplicationEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/LoginCacheManager.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/LoginCacheManager.java new file mode 100644 index 0000000000..3ecd741350 --- /dev/null +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/LoginCacheManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.ui.request.interceptor.cache; + +import io.entgra.ui.request.interceptor.util.HandlerConstants; + +import javax.cache.Cache; +import javax.cache.CacheManager; +import javax.cache.Caching; + +/** + * Contains necessary functions to manage oAuth app cache during login handling + */ +public class LoginCacheManager { + + private CacheManager cacheManager = null; + private Cache cache = null; + + /** + * Initialize the cache manager if it is not already initialized + */ + public void initializeCacheManager() { + cacheManager = Caching.getCacheManagerFactory().getCacheManager(HandlerConstants.LOGIN_CACHE); + } + + /** + * Persists OAuth app cache if it is not already persisted + * + * @param oAuthAppCacheKey - The identifier key of the cache + * @param oAuthApp - The value of the cache which contains OAuth app data + */ + public void addOAuthAppToCache(OAuthAppCacheKey oAuthAppCacheKey, OAuthApp oAuthApp) { + cache = cacheManager.getCache(HandlerConstants.LOGIN_CACHE); + cache.put(oAuthAppCacheKey, oAuthApp); + } + + /** + * Retrieves the OAuth app cache + * + * @param oAuthAppCacheKey - The key to identify the cache + * @return - Returns OAuthApp object + */ + public OAuthApp getOAuthAppCache(OAuthAppCacheKey oAuthAppCacheKey) { + cache = cacheManager.getCache(HandlerConstants.LOGIN_CACHE); + return cache.get(oAuthAppCacheKey); + } +} diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthApp.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthApp.java new file mode 100644 index 0000000000..db721ea992 --- /dev/null +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthApp.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.ui.request.interceptor.cache; + +/** + * The data object used for Login Cache + */ +public class OAuthApp { + + private String appName; + private String appOwner; + private String clientId; + private String clientSecret; + private String encodedClientApp; + + public OAuthApp(String appName, String appOwner, String clientId, String clientSecret, String encodedClientApp) { + this.appName = appName; + this.appOwner = appOwner; + this.clientId = clientId; + this.clientSecret = clientSecret; + this.encodedClientApp = encodedClientApp; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getAppOwner() { + return appOwner; + } + + public void setAppOwner(String appOwner) { + this.appOwner = appOwner; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getEncodedClientApp() { + return encodedClientApp; + } + + public void setEncodedClientApp(String encodedClientApp) { + this.encodedClientApp = encodedClientApp; + } +} diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthAppCacheKey.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthAppCacheKey.java new file mode 100644 index 0000000000..aa03eade5a --- /dev/null +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/cache/OAuthAppCacheKey.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.ui.request.interceptor.cache; + +import java.util.Objects; + +/** + * The key object used for Login Cache + */ +public class OAuthAppCacheKey { + + private String appName; + private String appOwner; + private volatile int hashCode; + + public OAuthAppCacheKey(String appName, String appOwner) { + this.appName = appName; + this.appOwner = appOwner; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getAppOwner() { + return appOwner; + } + + public void setAppOwner(String appOwner) { + this.appOwner = appOwner; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj instanceof OAuthAppCacheKey) { + final OAuthAppCacheKey other = (OAuthAppCacheKey) obj; + String thisId = this.appName + "-" + this.appOwner; + String otherId = other.appName + "-" + other.appOwner; + return thisId.equals(otherId); + } + return false; + } + + @Override + public int hashCode() { + if (hashCode == 0) { + hashCode = Objects.hash(appName, appOwner); + } + return hashCode; + } +} diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java index 3d4255c0aa..56e50769b8 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java @@ -55,6 +55,7 @@ public class HandlerConstants { public static final String PASSWORD_GRANT_TYPE = "password"; public static final String JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer"; public static final String PRODUCTION_KEY = "PRODUCTION"; + public static final String LOGIN_CACHE = "LOGIN_CACHE"; public static final String SCHEME_SEPARATOR = "://"; public static final String COLON = ":";