diff --git a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/GrafanaAPIProxyService.java b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/GrafanaAPIProxyService.java index 81f6f9bf4a..b33671879d 100644 --- a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/GrafanaAPIProxyService.java +++ b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/GrafanaAPIProxyService.java @@ -94,6 +94,23 @@ public interface GrafanaAPIProxyService { ) Response frontendMetrics(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo); + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/user/auth-tokens/rotate") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Rotate authentication tokens", + tags = "Analytics", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "grafana:api:view") + }) + } + ) + Response rotateAuthToken(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo); + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/dashboards/uid/{uid}") @@ -110,6 +127,22 @@ public interface GrafanaAPIProxyService { ) Response getDashboard(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException; + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/folders/{uid}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Grafana dashboard folder information", + tags = "Analytics", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "grafana:api:view") + }) + } + ) + Response getFolders(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException; + @GET @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @@ -127,6 +160,23 @@ public interface GrafanaAPIProxyService { ) Response getAnnotations(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException; + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/prometheus/grafana/api/v1/rules") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Accessing Grafana Prometheus rule information", + tags = "Analytics", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "grafana:api:view") + }) + } + ) + Response prometheusRuleInfo(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) throws ClassNotFoundException; + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/alerts/states-for-dashboard") diff --git a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/GrafanaAPIProxyServiceImpl.java b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/GrafanaAPIProxyServiceImpl.java index e821d8597f..62523bb483 100644 --- a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/GrafanaAPIProxyServiceImpl.java +++ b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/GrafanaAPIProxyServiceImpl.java @@ -26,6 +26,8 @@ import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.Grafa import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.impl.util.GrafanaRequestHandlerUtil; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.common.exception.GrafanaManagementException; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.bean.GrafanaPanelIdentifier; +import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfiguration; +import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfigurationManager; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.MaliciousQueryAttempt; import io.entgra.device.mgt.core.device.mgt.common.exceptions.DBConnectionException; import org.apache.commons.logging.Log; @@ -56,9 +58,13 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService { @Override public Response queryDatasource(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) { try { + GrafanaConfiguration configuration = GrafanaConfigurationManager.getInstance().getGrafanaConfiguration(); GrafanaPanelIdentifier panelIdentifier = GrafanaRequestHandlerUtil.getPanelIdentifier(headers); - GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(), - panelIdentifier.getPanelId(), requestUriInfo.getRequestUri()); + boolean queryValidationConfig = configuration.getValidationConfig().getDSQueryValidation(); + if (queryValidationConfig) { + GrafanaMgtAPIUtils.getGrafanaQueryService().buildSafeQuery(body, panelIdentifier.getDashboardId(), + panelIdentifier.getPanelId(), requestUriInfo.getRequestUri()); + } return GrafanaRequestHandlerUtil.proxyPassPostRequest(body, requestUriInfo, panelIdentifier.getOrgId()); } catch (MaliciousQueryAttempt e) { return Response.status(Response.Status.BAD_REQUEST).entity( @@ -83,6 +89,15 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService { return proxyPassPostRequest(body, headers, requestUriInfo); } + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/user/auth-tokens/rotate") + @Override + public Response rotateAuthToken(JsonObject body, @Context HttpHeaders headers, @Context UriInfo requestUriInfo) { + return proxyPassPostRequest(body, headers, requestUriInfo); + } + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/dashboards/uid/{uid}") @@ -91,6 +106,14 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService { return proxyPassGetRequest(headers, requestUriInfo); } + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/folders/{uid}") + @Override + public Response getFolders(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) { + return proxyPassGetRequest(headers, requestUriInfo); + } + @GET @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @@ -99,6 +122,16 @@ public class GrafanaAPIProxyServiceImpl implements GrafanaAPIProxyService { public Response getAnnotations(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) { return proxyPassGetRequest(headers, requestUriInfo); } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/prometheus/grafana/api/v1/rules") + @Override + public Response prometheusRuleInfo(@Context HttpHeaders headers, @Context UriInfo requestUriInfo) { + return proxyPassGetRequest(headers, requestUriInfo); + } + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/alerts/states-for-dashboard") diff --git a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/util/GrafanaRequestHandlerUtil.java b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/util/GrafanaRequestHandlerUtil.java index ddc36731db..b582c3b11a 100644 --- a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/util/GrafanaRequestHandlerUtil.java +++ b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/api/impl/util/GrafanaRequestHandlerUtil.java @@ -22,6 +22,8 @@ import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.bean.ErrorRespo import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.api.exception.RefererNotValid; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.common.exception.GrafanaManagementException; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.bean.GrafanaPanelIdentifier; +import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfiguration; +import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.GrafanaConfigurationManager; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.exception.GrafanaEnvVariablesNotDefined; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.util.GrafanaConstants; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.util.GrafanaUtil; @@ -120,19 +122,23 @@ public class GrafanaRequestHandlerUtil { return path; } - public static GrafanaPanelIdentifier getPanelIdentifier(HttpHeaders headers) throws RefererNotValid { + public static GrafanaPanelIdentifier getPanelIdentifier(HttpHeaders headers) throws RefererNotValid, GrafanaManagementException { String referer = headers.getHeaderString(GrafanaConstants.REFERER_HEADER); - if(referer == null) { + if (referer == null) { String errMsg = "Request does not contain Referer header"; log.error(errMsg); throw new RefererNotValid(errMsg); } + GrafanaConfiguration configuration = GrafanaConfigurationManager.getInstance().getGrafanaConfiguration(); + boolean dashboardIntegrationConfig = configuration.getValidationConfig().getDashboardIntegration(); GrafanaPanelIdentifier panelIdentifier = GrafanaUtil.getPanelIdentifierFromReferer(referer); - if(panelIdentifier.getDashboardId() == null || - panelIdentifier.getPanelId() == null || panelIdentifier.getOrgId() == null) { - String errMsg = "Referer must contain dashboardId, panelId and orgId"; - log.error(errMsg); - throw new RefererNotValid(errMsg); + if (!dashboardIntegrationConfig) { + if (panelIdentifier.getDashboardId() == null || + panelIdentifier.getPanelId() == null || panelIdentifier.getOrgId() == null) { + String errMsg = "Referer must contain dashboardId, panelId, and orgId"; + log.error(errMsg); + throw new RefererNotValid(errMsg); + } } return panelIdentifier; } diff --git a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/GrafanaConfiguration.java b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/GrafanaConfiguration.java index bf2cbce90f..137dc86025 100644 --- a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/GrafanaConfiguration.java +++ b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/GrafanaConfiguration.java @@ -19,6 +19,7 @@ package io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.CacheConfiguration; +import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.ValidationConfig; import io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean.User; import javax.xml.bind.annotation.XmlElement; @@ -30,6 +31,7 @@ import java.util.List; public class GrafanaConfiguration { private User adminUser; + private ValidationConfig validationConfig; private List caches; @XmlElement(name = "AdminUser") @@ -37,6 +39,15 @@ public class GrafanaConfiguration { return adminUser; } + @XmlElement(name = "ValidationConfig") + public ValidationConfig getValidationConfig() { + return validationConfig; + } + + public void setValidationConfig(ValidationConfig validationConfig) { + this.validationConfig = validationConfig; + } + public void setAdminUser(User user) { this.adminUser = user; } diff --git a/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/xml/bean/ValidationConfig.java b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/xml/bean/ValidationConfig.java new file mode 100644 index 0000000000..b15955bbe2 --- /dev/null +++ b/components/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.core/src/main/java/io/entgra/device/mgt/core/analytics/mgt/grafana/proxy/core/config/xml/bean/ValidationConfig.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.analytics.mgt.grafana.proxy.core.config.xml.bean; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "ValidationConfig") +public class ValidationConfig { + private boolean dsQueryValidation; + private boolean dashboardIntegration; + + @XmlElement(name = "DSQueryValidation") + public boolean getDSQueryValidation() { + return dsQueryValidation; + } + + public void setDSQueryValidation(boolean dsQueryValidation) { + this.dsQueryValidation = dsQueryValidation; + } + + @XmlElement(name = "DashboardIntegration") + public boolean getDashboardIntegration() { + return dashboardIntegration; + } + + public void setDashboardIntegration(boolean dashboardIntegration) { + this.dashboardIntegration = dashboardIntegration; + } +} diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java index 82bc8abed7..aebdde8967 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java @@ -46,6 +46,7 @@ import io.entgra.device.mgt.core.device.mgt.core.config.DeviceManagementConfig; import io.entgra.device.mgt.core.device.mgt.core.config.permission.DefaultPermission; import io.entgra.device.mgt.core.device.mgt.core.config.permission.DefaultPermissions; import io.entgra.device.mgt.core.device.mgt.core.config.permission.ScopeMapping; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -68,6 +69,8 @@ import org.wso2.carbon.user.core.tenant.TenantSearchResult; import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; +import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionUtils; +import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.PermissionManagementException; import java.io.BufferedReader; import java.io.File; @@ -588,9 +591,17 @@ public class APIPublisherServiceImpl implements APIPublisherService { if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getName())) { publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope); + // todo: permission changed in update path, is not handled yet. } else { - // todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list - log.warn(scope.getName() + " not available as shared scope"); + // This scope doesn't have an api attached. + log.warn(scope.getName() + " not available as shared, add as new scope"); + publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope); + // add permission if not exist + try { + PermissionUtils.putPermission(permission); + } catch(PermissionManagementException e) { + log.error("Error when adding permission ", e); + } } } for (String role : rolePermissions.keySet()) { diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/CategorizedSubscriptionResult.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/CategorizedSubscriptionResult.java new file mode 100644 index 0000000000..28cc436115 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/CategorizedSubscriptionResult.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.application.mgt.common; + +import java.util.List; + +public class CategorizedSubscriptionResult { + private List installedDevices; + private List pendingDevices; + private List errorDevices; + private List newDevices; + private List subscribedDevices; + + public CategorizedSubscriptionResult(List installedDevices, + List pendingDevices, + List errorDevices) { + this.installedDevices = installedDevices; + this.pendingDevices = pendingDevices; + this.errorDevices = errorDevices; + this.newDevices = null; + this.subscribedDevices = null; + } + + public CategorizedSubscriptionResult(List installedDevices, + List pendingDevices, + List errorDevices, + List newDevices) { + this.installedDevices = installedDevices; + this.pendingDevices = pendingDevices; + this.errorDevices = errorDevices; + this.newDevices = newDevices; + this.subscribedDevices = null; + } + + public CategorizedSubscriptionResult(List installedDevices, + List pendingDevices, + List errorDevices, + List newDevices, + List subscribedDevices) { + this.installedDevices = installedDevices; + this.pendingDevices = pendingDevices; + this.errorDevices = errorDevices; + this.newDevices = newDevices; + this.subscribedDevices = subscribedDevices; + } + + public List getInstalledDevices() { + return installedDevices; + } + + public void setInstalledDevices(List installedDevices) { + this.installedDevices = installedDevices; + } + + public List getPendingDevices() { + return pendingDevices; + } + + public void setPendingDevices(List pendingDevices) { + this.pendingDevices = pendingDevices; + } + + public List getErrorDevices() { + return errorDevices; + } + + public void setErrorDevices(List errorDevices) { + this.errorDevices = errorDevices; + } + + public List getNewDevices() { + return newDevices; + } + + public void setNewDevices(List newDevices) { + this.newDevices = newDevices; + } + + public List getSubscribedDevices() { + return subscribedDevices; + } + + public void setSubscribedDevices(List subscribedDevices) { + this.subscribedDevices = subscribedDevices; + } +} + diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/DeviceSubscriptionData.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/DeviceSubscriptionData.java index ffc1c4635f..b77b2ba599 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/DeviceSubscriptionData.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/DeviceSubscriptionData.java @@ -20,16 +20,28 @@ package io.entgra.device.mgt.core.application.mgt.common; import io.entgra.device.mgt.core.device.mgt.common.Device; +import java.sql.Timestamp; + public class DeviceSubscriptionData { private int subId; private String action; - private long actionTriggeredTimestamp; + private Timestamp actionTriggeredTimestamp; + private String actionTriggeredFrom; private String actionTriggeredBy; private String actionType; private String status; private Device device; private String currentInstalledVersion; + private int deviceId; + private String deviceOwner; + private String deviceStatus; + private boolean unsubscribed; + private String unsubscribedBy; + private Timestamp unsubscribedTimestamp; + private String deviceName; + private String deviceIdentifier; + private String type; public String getAction() { return action; @@ -39,14 +51,6 @@ public class DeviceSubscriptionData { this.action = action; } - public long getActionTriggeredTimestamp() { - return actionTriggeredTimestamp; - } - - public void setActionTriggeredTimestamp(long actionTriggeredTimestamp) { - this.actionTriggeredTimestamp = actionTriggeredTimestamp; - } - public String getActionTriggeredBy() { return actionTriggeredBy; } @@ -79,9 +83,13 @@ public class DeviceSubscriptionData { this.device = device; } - public String getCurrentInstalledVersion() { return currentInstalledVersion; } + public String getCurrentInstalledVersion() { + return currentInstalledVersion; + } - public void setCurrentInstalledVersion(String currentInstalledVersion) { this.currentInstalledVersion = currentInstalledVersion; } + public void setCurrentInstalledVersion(String currentInstalledVersion) { + this.currentInstalledVersion = currentInstalledVersion; + } public int getSubId() { return subId; @@ -90,4 +98,92 @@ public class DeviceSubscriptionData { public void setSubId(int subId) { this.subId = subId; } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public String getActionTriggeredFrom() { + return actionTriggeredFrom; + } + + public void setActionTriggeredFrom(String actionTriggeredFrom) { + this.actionTriggeredFrom = actionTriggeredFrom; + } + + public Timestamp getActionTriggeredTimestamp() { + return actionTriggeredTimestamp; + } + + public void setActionTriggeredTimestamp(Timestamp actionTriggeredTimestamp) { + this.actionTriggeredTimestamp = actionTriggeredTimestamp; + } + + public String getDeviceOwner() { + return deviceOwner; + } + + public void setDeviceOwner(String deviceOwner) { + this.deviceOwner = deviceOwner; + } + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public boolean isUnsubscribed() { + return unsubscribed; + } + + public void setUnsubscribed(boolean unsubscribed) { + this.unsubscribed = unsubscribed; + } + + public String getUnsubscribedBy() { + return unsubscribedBy; + } + + public void setUnsubscribedBy(String unsubscribedBy) { + this.unsubscribedBy = unsubscribedBy; + } + + public Timestamp getUnsubscribedTimestamp() { + return unsubscribedTimestamp; + } + + public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) { + this.unsubscribedTimestamp = unsubscribedTimestamp; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDeviceIdentifier() { + return deviceIdentifier; + } + + public void setDeviceIdentifier(String deviceIdentifier) { + this.deviceIdentifier = deviceIdentifier; + } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/CategorizedSubscriptionCountsDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/CategorizedSubscriptionCountsDTO.java new file mode 100644 index 0000000000..2ee5bb3cb0 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/CategorizedSubscriptionCountsDTO.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.application.mgt.common.dto; + +public class CategorizedSubscriptionCountsDTO { + private String subscriptionType; + private int subscriptionCount; + private int unsubscriptionCount; + + public CategorizedSubscriptionCountsDTO(String subscriptionType, int subscriptionCount, int unsubscriptionCount) { + this.subscriptionType = subscriptionType; + this.subscriptionCount = subscriptionCount; + this.unsubscriptionCount = unsubscriptionCount; + } + + public String getSubscriptionType() { + return subscriptionType; + } + + public void setSubscriptionType(String subscriptionType) { + this.subscriptionType = subscriptionType; + } + + public int getSubscriptionCount() { + return subscriptionCount; + } + + public void setSubscriptionCount(int subscriptionCount) { + this.subscriptionCount = subscriptionCount; + } + + public int getUnsubscriptionCount() { + return unsubscriptionCount; + } + + public void setUnsubscriptionCount(int unsubscriptionCount) { + this.unsubscriptionCount = unsubscriptionCount; + } +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceOperationDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceOperationDTO.java new file mode 100644 index 0000000000..75699431a2 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceOperationDTO.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.application.mgt.common.dto; + +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationResponseDTO; + +import java.sql.Timestamp; +import java.util.List; + +public class DeviceOperationDTO { + private int deviceId; + private String uuid; + private String status; + private int operationId; + private String actionTriggeredFrom; + private Timestamp actionTriggeredAt; + private int appReleaseId; + private String operationCode; + private Object operationDetails; + private Object operationProperties; + private List operationResponses; + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getOperationId() { + return operationId; + } + + public void setOperationId(int operationId) { + this.operationId = operationId; + } + + public String getActionTriggeredFrom() { + return actionTriggeredFrom; + } + + public void setActionTriggeredFrom(String actionTriggeredFrom) { + this.actionTriggeredFrom = actionTriggeredFrom; + } + + public Timestamp getActionTriggeredAt() { + return actionTriggeredAt; + } + + public void setActionTriggeredAt(Timestamp actionTriggeredAt) { + this.actionTriggeredAt = actionTriggeredAt; + } + + public int getAppReleaseId() { + return appReleaseId; + } + + public void setAppReleaseId(int appReleaseId) { + this.appReleaseId = appReleaseId; + } + + public String getOperationCode() { + return operationCode; + } + + public void setOperationCode(String operationCode) { + this.operationCode = operationCode; + } + + public Object getOperationDetails() { + return operationDetails; + } + + public void setOperationDetails(Object operationDetails) { + this.operationDetails = operationDetails; + } + + public Object getOperationProperties() { + return operationProperties; + } + + public void setOperationProperties(Object operationProperties) { + this.operationProperties = operationProperties; + } + + public List getOperationResponses() { + return operationResponses; + } + + public void setOperationResponses(List operationResponses) { + this.operationResponses = operationResponses; + } +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionDTO.java index 9a30ec07c2..3306256b19 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionDTO.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionDTO.java @@ -31,44 +31,94 @@ public class DeviceSubscriptionDTO { private String actionTriggeredFrom; private String status; private int deviceId; + private int appReleaseId; + private String appUuid; - public int getId() { return id; } + public int getId() { + return id; + } - public void setId(int id) { this.id = id; } + public void setId(int id) { + this.id = id; + } - public String getSubscribedBy() { return subscribedBy; } + public String getSubscribedBy() { + return subscribedBy; + } - public void setSubscribedBy(String subscribedBy) { this.subscribedBy = subscribedBy; } + public void setSubscribedBy(String subscribedBy) { + this.subscribedBy = subscribedBy; + } - public Timestamp getSubscribedTimestamp() { return subscribedTimestamp; } + public Timestamp getSubscribedTimestamp() { + return subscribedTimestamp; + } public void setSubscribedTimestamp(Timestamp subscribedTimestamp) { this.subscribedTimestamp = subscribedTimestamp; } - public boolean isUnsubscribed() { return isUnsubscribed; } + public boolean isUnsubscribed() { + return isUnsubscribed; + } - public void setUnsubscribed(boolean unsubscribed) { isUnsubscribed = unsubscribed; } + public void setUnsubscribed(boolean unsubscribed) { + isUnsubscribed = unsubscribed; + } - public String getUnsubscribedBy() { return unsubscribedBy; } + public String getUnsubscribedBy() { + return unsubscribedBy; + } - public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; } + public void setUnsubscribedBy(String unsubscribedBy) { + this.unsubscribedBy = unsubscribedBy; + } - public Timestamp getUnsubscribedTimestamp() { return unsubscribedTimestamp; } + public Timestamp getUnsubscribedTimestamp() { + return unsubscribedTimestamp; + } public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) { this.unsubscribedTimestamp = unsubscribedTimestamp; } - public String getActionTriggeredFrom() { return actionTriggeredFrom; } + public String getActionTriggeredFrom() { + return actionTriggeredFrom; + } + + public void setActionTriggeredFrom(String actionTriggeredFrom) { + this.actionTriggeredFrom = actionTriggeredFrom; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getDeviceId() { + return deviceId; + } - public void setActionTriggeredFrom(String actionTriggeredFrom) { this.actionTriggeredFrom = actionTriggeredFrom; } + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } - public String getStatus() { return status; } + public int getAppReleaseId() { + return appReleaseId; + } - public void setStatus(String status) { this.status = status; } + public void setAppReleaseId(int appReleaseId) { + this.appReleaseId = appReleaseId; + } - public int getDeviceId() { return deviceId; } + public String getAppUuid() { + return appUuid; + } - public void setDeviceId(int deviceId) { this.deviceId = deviceId; } + public void setAppUuid(String appUuid) { + this.appUuid = appUuid; + } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionResponseDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionResponseDTO.java new file mode 100644 index 0000000000..5d132bfd37 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/DeviceSubscriptionResponseDTO.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.application.mgt.common.dto; + +import io.entgra.device.mgt.core.application.mgt.common.CategorizedSubscriptionResult; + +import java.util.Map; + +public class DeviceSubscriptionResponseDTO { + private int deviceCount; + private Map statusPercentages; + private CategorizedSubscriptionResult devices; + + public DeviceSubscriptionResponseDTO(int deviceCount, Map statusPercentages, + CategorizedSubscriptionResult devices) { + this.deviceCount = deviceCount; + this.statusPercentages = statusPercentages; + this.devices = devices; + } + + public int getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(int deviceCount) { + this.deviceCount = deviceCount; + } + + public Map getStatusPercentages() { + return statusPercentages; + } + + public void setStatusPercentages(Map statusPercentages) { + this.statusPercentages = statusPercentages; + } + + public CategorizedSubscriptionResult getDevices() { + return devices; + } + + public void setDevices(CategorizedSubscriptionResult devices) { + this.devices = devices; + } +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/GroupSubscriptionDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/GroupSubscriptionDTO.java index 3d9e6dfd2c..76a7b39d2d 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/GroupSubscriptionDTO.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/GroupSubscriptionDTO.java @@ -22,6 +22,7 @@ import java.sql.Timestamp; public class GroupSubscriptionDTO { private int id; + private String groupName; private String subscribedBy; private Timestamp subscribedTimestamp; private boolean isUnsubscribed; @@ -29,6 +30,7 @@ public class GroupSubscriptionDTO { private Timestamp unsubscribedTimestamp; private String subscribedFrom; private int groupdId; + private int appReleaseId; public int getId() { return id; } @@ -61,4 +63,20 @@ public class GroupSubscriptionDTO { public int getGroupdId() { return groupdId; } public void setGroupdId(int groupdId) { this.groupdId = groupdId; } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public int getAppReleaseId() { + return appReleaseId; + } + + public void setAppReleaseId(int appReleaseId) { + this.appReleaseId = appReleaseId; + } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/RoleSubscriptionDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/RoleSubscriptionDTO.java index 869ed1fd6d..b8139181de 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/RoleSubscriptionDTO.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/RoleSubscriptionDTO.java @@ -18,51 +18,115 @@ package io.entgra.device.mgt.core.application.mgt.common.dto; +import io.entgra.device.mgt.core.application.mgt.common.CategorizedSubscriptionResult; + import java.sql.Timestamp; +import java.util.Map; public class RoleSubscriptionDTO { - private int id; private String subscribedBy; private Timestamp subscribedTimestamp; private boolean isUnsubscribed; + private boolean unsubscribed; private String unsubscribedBy; private Timestamp unsubscribedTimestamp; private String subscribedFrom; private String roleName; + private int appReleaseId; + private int deviceCount; + private Map statusPercentages; + private CategorizedSubscriptionResult devices; - public int getId() { return id; } - - public void setId(int id) { this.id = id; } - - public String getSubscribedBy() { return subscribedBy; } + public String getSubscribedBy() { + return subscribedBy; + } - public void setSubscribedBy(String subscribedBy) { this.subscribedBy = subscribedBy; } + public void setSubscribedBy(String subscribedBy) { + this.subscribedBy = subscribedBy; + } - public Timestamp getSubscribedTimestamp() { return subscribedTimestamp; } + public Timestamp getSubscribedTimestamp() { + return subscribedTimestamp; + } public void setSubscribedTimestamp(Timestamp subscribedTimestamp) { this.subscribedTimestamp = subscribedTimestamp; } - public boolean isUnsubscribed() { return isUnsubscribed; } + public boolean getUnsubscribed() { + return unsubscribed; + } - public void setUnsubscribed(boolean unsubscribed) { isUnsubscribed = unsubscribed; } + public void setUnsubscribed(boolean unsubscribed) { + this.unsubscribed = unsubscribed; + } - public String getUnsubscribedBy() { return unsubscribedBy; } + public boolean isUnsubscribed() { + return isUnsubscribed; + } - public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; } + public String getUnsubscribedBy() { + return unsubscribedBy; + } + + public void setUnsubscribedBy(String unsubscribedBy) { + this.unsubscribedBy = unsubscribedBy; + } - public Timestamp getUnsubscribedTimestamp() { return unsubscribedTimestamp; } + public Timestamp getUnsubscribedTimestamp() { + return unsubscribedTimestamp; + } public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) { this.unsubscribedTimestamp = unsubscribedTimestamp; } - public String getSubscribedFrom() { return subscribedFrom; } + public String getSubscribedFrom() { + return subscribedFrom; + } + + public void setSubscribedFrom(String subscribedFrom) { + this.subscribedFrom = subscribedFrom; + } + + public String getRoleName() { + return roleName; + } - public void setSubscribedFrom(String subscribedFrom) { this.subscribedFrom = subscribedFrom; } + public void setRoleName(String roleName) { + this.roleName = roleName; + } - public String getRoleName() { return roleName; } + public int getAppReleaseId() { + return appReleaseId; + } + + public void setAppReleaseId(int appReleaseId) { + this.appReleaseId = appReleaseId; + } + + public int getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(int deviceCount) { + this.deviceCount = deviceCount; + } + + public Map getStatusPercentages() { + return statusPercentages; + } + + public void setStatusPercentages(Map statusPercentages) { + this.statusPercentages = statusPercentages; + } + + public CategorizedSubscriptionResult getDevices() { + return devices; + } + + public void setDevices(CategorizedSubscriptionResult devices) { + this.devices = devices; + } - public void setRoleName(String roleName) { this.roleName = roleName; } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/SubscriptionResponseDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/SubscriptionResponseDTO.java new file mode 100644 index 0000000000..03967ec94d --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/SubscriptionResponseDTO.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.application.mgt.common.dto; + +import java.util.List; + +public class SubscriptionResponseDTO { + + private String UUID; + private List subscriptions; + private List DevicesOperations; + + public String getUUID() { + return UUID; + } + + public void setUUID(String UUID) { + this.UUID = UUID; + } + + public List getDevicesOperations() { + return DevicesOperations; + } + + public void setDevicesOperations(List devicesOperations) { + DevicesOperations = devicesOperations; + } + + public List getSubscriptions() { + return subscriptions; + } + + public void setSubscriptions(List subscriptions) { + this.subscriptions = subscriptions; + } +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/SubscriptionsDTO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/SubscriptionsDTO.java new file mode 100644 index 0000000000..cb127696e3 --- /dev/null +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/SubscriptionsDTO.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.application.mgt.common.dto; + +import io.entgra.device.mgt.core.application.mgt.common.CategorizedSubscriptionResult; + +import java.sql.Timestamp; +import java.util.Map; + +public class SubscriptionsDTO { + private int id; + private String owner; + private String name; + private String subscribedBy; + private Timestamp subscribedTimestamp; + private boolean unsubscribed; + private String unsubscribedBy; + private Timestamp unsubscribedTimestamp; + private String subscribedFrom; + private int appReleaseId; + private int deviceCount; + private String deviceOwner; + private String deviceStatus; + private Map statusPercentages; + private CategorizedSubscriptionResult devices; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSubscribedBy() { + return subscribedBy; + } + + public void setSubscribedBy(String subscribedBy) { + this.subscribedBy = subscribedBy; + } + + public Timestamp getSubscribedTimestamp() { + return subscribedTimestamp; + } + + public void setSubscribedTimestamp(Timestamp subscribedTimestamp) { + this.subscribedTimestamp = subscribedTimestamp; + } + + public String getUnsubscribedBy() { + return unsubscribedBy; + } + + public void setUnsubscribedBy(String unsubscribedBy) { + this.unsubscribedBy = unsubscribedBy; + } + + public Timestamp getUnsubscribedTimestamp() { + return unsubscribedTimestamp; + } + + public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) { + this.unsubscribedTimestamp = unsubscribedTimestamp; + } + + public String getSubscribedFrom() { + return subscribedFrom; + } + + public void setSubscribedFrom(String subscribedFrom) { + this.subscribedFrom = subscribedFrom; + } + + public int getAppReleaseId() { + return appReleaseId; + } + + public void setAppReleaseId(int appReleaseId) { + this.appReleaseId = appReleaseId; + } + + public int getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(int deviceCount) { + this.deviceCount = deviceCount; + } + + public String getDeviceOwner() { + return deviceOwner; + } + + public void setDeviceOwner(String deviceOwner) { + this.deviceOwner = deviceOwner; + } + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public Map getStatusPercentages() { + return statusPercentages; + } + + public void setStatusPercentages(Map statusPercentages) { + this.statusPercentages = statusPercentages; + } + + public CategorizedSubscriptionResult getDevices() { + return devices; + } + + public void setDevices(CategorizedSubscriptionResult devices) { + this.devices = devices; + } + + public boolean getUnsubscribed() { + return unsubscribed; + } + + public void setUnsubscribed(boolean unsubscribed) { + this.unsubscribed = unsubscribed; + } +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/SubscriptionManager.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/SubscriptionManager.java index cd66878019..1cbeda5f08 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/SubscriptionManager.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/services/SubscriptionManager.java @@ -18,9 +18,14 @@ package io.entgra.device.mgt.core.application.mgt.common.services; import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstallResponse; +import io.entgra.device.mgt.core.application.mgt.common.CategorizedSubscriptionResult; import io.entgra.device.mgt.core.application.mgt.common.ExecutionStatus; import io.entgra.device.mgt.core.application.mgt.common.SubscriptionType; +import io.entgra.device.mgt.core.application.mgt.common.dto.CategorizedSubscriptionCountsDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.ScheduledSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.SubscriptionsDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceOperationDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceSubscriptionResponseDTO; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; import io.entgra.device.mgt.core.application.mgt.common.exception.SubscriptionManagementException; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; @@ -194,7 +199,7 @@ public interface SubscriptionManager { * application release for given UUID, if an error occurred while getting device details of subscribed device ids, * if an error occurred while getting subscription details of given application release UUID. */ - PaginationResult getAppSubscriptionDetails(PaginationRequest request, String appUUID, String actionStatus, String action, String installedVersion) + CategorizedSubscriptionResult getAppSubscriptionDetails(PaginationRequest request, String appUUID, String actionStatus, String action, String installedVersion) throws ApplicationManagementException; /*** @@ -217,4 +222,94 @@ public interface SubscriptionManager { * @throws {@link SubscriptionManagementException} Exception of the subscription management */ Activity getOperationAppDetails(String id) throws SubscriptionManagementException; + + /** + * Retrieves the group details associated with a given app release UUID. + * + * @param uuid the UUID of the app release + * @param subscriptionStatus the status of the subscription (subscribed or unsubscribed) + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link SubscriptionsDTO} which contains the details of subscriptions. + * @throws ApplicationManagementException if an error occurs while fetching the group details + */ + List getGroupsSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException; + + /** + * Retrieves the user details associated with a given app release UUID. + * + * @param uuid the UUID of the app release + * @param subscriptionStatus the status of the subscription (subscribed or unsubscribed) + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link SubscriptionsDTO} which contains the details of subscriptions. + * @throws ApplicationManagementException if an error occurs while fetching the user details + */ + List getUserSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException; + + /** + * Retrieves the Role details associated with a given app release UUID. + * + * @param uuid the UUID of the app release + * @param subscriptionStatus the status of the subscription (subscribed or unsubscribed) + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link SubscriptionsDTO} which contains the details of subscriptions. + * @throws ApplicationManagementException if an error occurs while fetching the role details + */ + List getRoleSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException; + + /** + * Retrieves the Device Subscription details associated with a given app release UUID. + * + * @param uuid the UUID of the app release + * @param subscriptionStatus the status of the subscription (subscribed or unsubscribed) + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link DeviceSubscriptionResponseDTO} which contains the details of device subscriptions. + * @throws ApplicationManagementException if an error occurs while fetching the device subscription details + */ + DeviceSubscriptionResponseDTO getDeviceSubscriptionsDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException; + + /** + * Retrieves the All Device details associated with a given app release UUID. + * + * @param uuid the UUID of the app release + * @param subscriptionStatus the status of the subscription (subscribed or unsubscribed) + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link DeviceSubscriptionResponseDTO} which contains the details of device subscriptions. + * @throws ApplicationManagementException if an error occurs while fetching the subscription details + */ + DeviceSubscriptionResponseDTO getAllSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException; + + /** + * This method is responsible for retrieving device subscription details related to the given UUID. + * + * @param deviceId the deviceId of the device that need to get operation details. + * @param uuid the UUID of the application release. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link DeviceOperationDTO} which contains the details of device subscriptions. + * @throws SubscriptionManagementException if there is an error while fetching the details. + */ + List getSubscriptionOperationsByUUIDAndDeviceID(int deviceId, String uuid, int offset, int limit) + throws ApplicationManagementException; + + /** + * This method is responsible for retrieving device counts details related to the given UUID. + * + * @param uuid the UUID of the application release. + * @return {@link List} which contains counts of subscriptions + and unsubscription for each subscription type. + * @throws SubscriptionManagementException if there is an error while fetching the details. + */ + List getSubscriptionCountsByUUID(String uuid) + throws ApplicationManagementException; + } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/SubscriptionDAO.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/SubscriptionDAO.java index 3213db3484..88465a4533 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/SubscriptionDAO.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/SubscriptionDAO.java @@ -18,8 +18,11 @@ package io.entgra.device.mgt.core.application.mgt.core.dao; import io.entgra.device.mgt.core.application.mgt.common.ExecutionStatus; -import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationReleaseDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.GroupSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.SubscriptionsDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationReleaseDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceOperationDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.ScheduledSubscriptionDTO; import io.entgra.device.mgt.core.application.mgt.common.exception.SubscriptionManagementException; import io.entgra.device.mgt.core.application.mgt.core.exception.ApplicationManagementDAOException; @@ -312,4 +315,201 @@ public interface SubscriptionDAO { * @throws ApplicationManagementDAOException thrown if an error occurs while deleting data */ void deleteScheduledSubscriptionByTenant(int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of group subscriptions related to a appReleaseId. + * + * @param appReleaseId the appReleaseId of the application release. + * @param unsubscribe the Status of the subscription. + * @param tenantId id of the current tenant. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link GroupSubscriptionDTO} which contains the details of group subscriptions. + * @throws ApplicationManagementDAOException if connection establishment fails. + */ + List getGroupsSubscriptionDetailsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of user subscriptions related to a appReleaseId. + * + * @param appReleaseId the appReleaseId of the application release. + * @param unsubscribe the Status of the subscription. + * @param tenantId id of the current tenant. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link SubscriptionsDTO} which contains the details of subscriptions. + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + List getUserSubscriptionsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, + int offset, int limit) throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of role subscriptions related to a appReleaseId. + * + * @param appReleaseId the appReleaseId of the application release. + * @param unsubscribe the Status of the subscription. + * @param tenantId id of the current tenant. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link SubscriptionsDTO} which contains the details of subscriptions. + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + List getRoleSubscriptionsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of device subscriptions related to a appReleaseId. + * + * @param appReleaseId the appReleaseId of the application release. + * @param unsubscribe the Status of the subscription. + * @param tenantId id of the current tenant. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link DeviceSubscriptionDTO} which contains the details of device subscriptions. + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + List getDeviceSubscriptionsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of device subscriptions related to a UUID. + * + * @param appReleaseId the appReleaseId of the application release. + * @param deviceId the deviceId of the device that need to get operation details. + * @param tenantId id of the current tenant. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link DeviceOperationDTO} which contains the details of device subscriptions. + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + List getSubscriptionOperationsByAppReleaseIDAndDeviceID(int appReleaseId, int deviceId, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of device subscriptions related to a UUID. + * + * @param appReleaseId the appReleaseId of the application release. + * @param unsubscribe the Status of the subscription. + * @param tenantId id of the current tenant. + * @param deviceIds deviceIds deviceIds to retrieve data. + * @return {@link DeviceOperationDTO} which contains the details of device subscriptions. + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + List getSubscriptionDetailsByDeviceIds(int appReleaseId, boolean unsubscribe, int tenantId, List deviceIds) + throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of device subscriptions related to a UUID. + * + * @param appReleaseId the appReleaseId of the application release. + * @param unsubscribe the Status of the subscription. + * @param tenantId id of the current tenant. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link DeviceOperationDTO} which contains the details of device subscriptions. + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + List getAllSubscriptionsDetails(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of all subscription types related to a UUID. + * + * @param appReleaseId the appReleaseId of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getAllSubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of all unsubscription types related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getAllUnsubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of device subscriptions related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getDeviceSubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of device unsubscription related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getDeviceUnsubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of group subscriptions related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getGroupSubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of group unsubscription related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getGroupUnsubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of role subscriptions related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getRoleSubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of role unsubscription related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getRoleUnsubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of user subscriptions related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getUserSubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the counts of user unsubscription related to a UUID. + * + * @param appReleaseId the UUID of the application release. + * @param tenantId id of the current tenant. + * @return {@link int} which contains the count of the subscription type + * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. + */ + int getUserUnsubscriptionCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java index 0aa4656866..d401b77aee 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java @@ -17,6 +17,9 @@ */ package io.entgra.device.mgt.core.application.mgt.core.dao.impl.subscription; +import io.entgra.device.mgt.core.application.mgt.common.dto.GroupSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceOperationDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.SubscriptionsDTO; import io.entgra.device.mgt.core.application.mgt.core.dao.SubscriptionDAO; import io.entgra.device.mgt.core.application.mgt.core.dao.impl.AbstractDAOImpl; import io.entgra.device.mgt.core.application.mgt.core.exception.UnexpectedServerErrorException; @@ -32,8 +35,19 @@ import io.entgra.device.mgt.core.application.mgt.common.dto.ScheduledSubscriptio import io.entgra.device.mgt.core.application.mgt.common.exception.DBConnectionException; import io.entgra.device.mgt.core.application.mgt.core.exception.ApplicationManagementDAOException; -import java.sql.*; -import java.util.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; +import java.util.stream.Collectors; public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements SubscriptionDAO { private static final Log log = LogFactory.getLog(GenericSubscriptionDAOImpl.class); @@ -1436,13 +1450,13 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc + "AR.PACKAGE_NAME, " + "AR.VERSION, " + "DS.SUBSCRIBED_BY, " - + "DS.STATUS, " + "DS.ACTION_TRIGGERED_FROM " + "FROM AP_APP_SUB_OP_MAPPING SOP " + "JOIN AP_DEVICE_SUBSCRIPTION DS ON SOP.AP_DEVICE_SUBSCRIPTION_ID = DS.ID " + "JOIN AP_APP_RELEASE AR ON DS.AP_APP_RELEASE_ID = AR.ID " + "JOIN AP_APP AP ON AP.ID = AR.AP_APP_ID " - + " WHERE SOP.OPERATION_ID = ? AND SOP.TENANT_ID = ?"; + + "WHERE SOP.OPERATION_ID = ? AND SOP.TENANT_ID = ? " + + "LIMIT 1"; Connection conn = this.getDBConnection(); try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -1626,4 +1640,803 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc throw new ApplicationManagementDAOException(msg, e); } } + + @Override + public List getGroupsSubscriptionDetailsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get groups related to the given AppReleaseID."); + } + try { + Connection conn = this.getDBConnection(); + List groupDetails = new ArrayList<>(); + + String subscriptionStatusTime = unsubscribe ? "GS.UNSUBSCRIBED_TIMESTAMP" : "GS.SUBSCRIBED_TIMESTAMP"; + String sql = "SELECT GS.GROUP_NAME, GS.SUBSCRIBED_BY, GS.SUBSCRIBED_TIMESTAMP, GS.UNSUBSCRIBED, " + + "GS.UNSUBSCRIBED_BY, GS.UNSUBSCRIBED_TIMESTAMP, GS.AP_APP_RELEASE_ID " + + "FROM AP_GROUP_SUBSCRIPTION GS " + + "WHERE GS.AP_APP_RELEASE_ID = ? AND GS.UNSUBSCRIBED = ? AND GS.TENANT_ID = ? " + + "ORDER BY " + subscriptionStatusTime + " DESC " + + "LIMIT ? OFFSET ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setBoolean(2, unsubscribe); + ps.setInt(3, tenantId); + ps.setInt(4, limit); + ps.setInt(5, offset); + + try (ResultSet rs = ps.executeQuery()) { + GroupSubscriptionDTO groupDetail; + while (rs.next()) { + groupDetail = new GroupSubscriptionDTO(); + groupDetail.setGroupName(rs.getString("GROUP_NAME")); + groupDetail.setSubscribedBy(rs.getString("SUBSCRIBED_BY")); + groupDetail.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_TIMESTAMP")); + groupDetail.setUnsubscribed(rs.getBoolean("UNSUBSCRIBED")); + groupDetail.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY")); + groupDetail.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_TIMESTAMP")); + groupDetail.setAppReleaseId(rs.getInt("AP_APP_RELEASE_ID")); + + groupDetails.add(groupDetail); + } + } + return groupDetails; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get groups for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting groups for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getUserSubscriptionsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, + int offset, int limit) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get user subscriptions related to the given UUID."); + } + try { + Connection conn = this.getDBConnection(); + List userSubscriptions = new ArrayList<>(); + + String subscriptionStatusTime = unsubscribe ? "US.UNSUBSCRIBED_TIMESTAMP" : "US.SUBSCRIBED_TIMESTAMP"; + String sql = "SELECT US.USER_NAME, US.SUBSCRIBED_BY, US.SUBSCRIBED_TIMESTAMP, US.UNSUBSCRIBED, " + + "US.UNSUBSCRIBED_BY, US.UNSUBSCRIBED_TIMESTAMP, US.AP_APP_RELEASE_ID " + + "FROM AP_USER_SUBSCRIPTION US " + + "WHERE US.AP_APP_RELEASE_ID = ? AND US.UNSUBSCRIBED = ? AND US.TENANT_ID = ? " + + "ORDER BY " + subscriptionStatusTime + " DESC " + + "LIMIT ? OFFSET ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setBoolean(2, unsubscribe); + ps.setInt(3, tenantId); + ps.setInt(4, limit); + ps.setInt(5, offset); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + SubscriptionsDTO userSubscription; + userSubscription = new SubscriptionsDTO(); + userSubscription.setName(rs.getString("USER_NAME")); + userSubscription.setSubscribedBy(rs.getString("SUBSCRIBED_BY")); + userSubscription.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_TIMESTAMP")); + userSubscription.setUnsubscribed(rs.getBoolean("UNSUBSCRIBED")); + userSubscription.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY")); + userSubscription.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_TIMESTAMP")); + userSubscription.setAppReleaseId(rs.getInt("AP_APP_RELEASE_ID")); + + userSubscriptions.add(userSubscription); + } + } + return userSubscriptions; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get user subscriptions for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting user subscriptions for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getRoleSubscriptionsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, int offset, + int limit) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get role subscriptions related to the given AppReleaseID."); + } + try { + Connection conn = this.getDBConnection(); + List roleSubscriptions = new ArrayList<>(); + + String subscriptionStatusTime = unsubscribe ? "ARS.UNSUBSCRIBED_TIMESTAMP" : "ARS.SUBSCRIBED_TIMESTAMP"; + String sql = "SELECT ARS.ROLE_NAME, ARS.SUBSCRIBED_BY, ARS.SUBSCRIBED_TIMESTAMP, ARS.UNSUBSCRIBED, " + + "ARS.UNSUBSCRIBED_BY, ARS.UNSUBSCRIBED_TIMESTAMP, ARS.AP_APP_RELEASE_ID " + + "FROM AP_ROLE_SUBSCRIPTION ARS " + + "WHERE ARS.AP_APP_RELEASE_ID = ? AND ARS.UNSUBSCRIBED = ? AND ARS.TENANT_ID = ? " + + "ORDER BY " + subscriptionStatusTime + " DESC " + + "LIMIT ? OFFSET ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setBoolean(2, unsubscribe); + ps.setInt(3, tenantId); + ps.setInt(4, limit); + ps.setInt(5, offset); + try (ResultSet rs = ps.executeQuery()) { + SubscriptionsDTO roleSubscription; + while (rs.next()) { + roleSubscription = new SubscriptionsDTO(); + roleSubscription.setName(rs.getString("ROLE_NAME")); + roleSubscription.setSubscribedBy(rs.getString("SUBSCRIBED_BY")); + roleSubscription.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_TIMESTAMP")); + roleSubscription.setUnsubscribed(rs.getBoolean("UNSUBSCRIBED")); + roleSubscription.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY")); + roleSubscription.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_TIMESTAMP")); + roleSubscription.setAppReleaseId(rs.getInt("AP_APP_RELEASE_ID")); + + roleSubscriptions.add(roleSubscription); + } + } + return roleSubscriptions; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get role subscriptions for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting role subscriptions for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getDeviceSubscriptionsByAppReleaseID(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get device subscriptions related to the given AppReleaseID."); + } + try { + Connection conn = this.getDBConnection(); + List deviceSubscriptions = new ArrayList<>(); + + String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP"; + String sql = "SELECT DS.DM_DEVICE_ID, " + + "DS.SUBSCRIBED_BY, " + + "DS.SUBSCRIBED_TIMESTAMP, " + + "DS.STATUS, " + + "DS.UNSUBSCRIBED, " + + "DS.UNSUBSCRIBED_BY, " + + "DS.UNSUBSCRIBED_TIMESTAMP, " + + "DS.AP_APP_RELEASE_ID " + + "FROM AP_DEVICE_SUBSCRIPTION DS " + + "WHERE DS.AP_APP_RELEASE_ID = ? " + + "AND DS.UNSUBSCRIBED = ? " + + "AND DS.TENANT_ID = ? " + + "AND DS.ACTION_TRIGGERED_FROM = 'DEVICE' " + + "ORDER BY " + subscriptionStatusTime + " DESC " + + "LIMIT ? OFFSET ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setBoolean(2, unsubscribe); + ps.setInt(3, tenantId); + ps.setInt(4, limit); + ps.setInt(5, offset); + try (ResultSet rs = ps.executeQuery()) { + DeviceSubscriptionDTO deviceSubscription; + while (rs.next()) { + deviceSubscription = new DeviceSubscriptionDTO(); + deviceSubscription.setDeviceId(rs.getInt("DM_DEVICE_ID")); + deviceSubscription.setSubscribedBy(rs.getString("SUBSCRIBED_BY")); + deviceSubscription.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_TIMESTAMP")); + deviceSubscription.setStatus(rs.getString("STATUS")); + deviceSubscription.setUnsubscribed(rs.getBoolean("UNSUBSCRIBED")); + deviceSubscription.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY")); + deviceSubscription.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_TIMESTAMP")); + deviceSubscription.setAppReleaseId(rs.getInt("AP_APP_RELEASE_ID")); + + deviceSubscriptions.add(deviceSubscription); + } + } + return deviceSubscriptions; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get device subscriptions for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting device subscriptions for the given UUID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getSubscriptionOperationsByAppReleaseIDAndDeviceID( + int appReleaseId, int deviceId, int tenantId, int offset, int limit) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get device subscriptions related to the given AppReleaseID and DeviceID."); + } + try { + Connection conn = this.getDBConnection(); + List deviceSubscriptions = new ArrayList<>(); + String sql = "SELECT " + + " ads.DM_DEVICE_ID, " + + " aasom.OPERATION_ID, " + + " ads.STATUS, " + + " ads.ACTION_TRIGGERED_FROM, " + + " ads.SUBSCRIBED_TIMESTAMP AS ACTION_TRIGGERED_AT, " + + " ads.AP_APP_RELEASE_ID " + + "FROM AP_APP_SUB_OP_MAPPING aasom " + + "JOIN AP_DEVICE_SUBSCRIPTION ads " + + "ON aasom.AP_DEVICE_SUBSCRIPTION_ID = ads.ID " + + "WHERE ads.AP_APP_RELEASE_ID = ? " + + "AND ads.DM_DEVICE_ID = ? " + + "AND ads.TENANT_ID = ? " + + "LIMIT ? OFFSET ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, deviceId); + ps.setInt(3, tenantId); + ps.setInt(4, limit); + ps.setInt(5, offset); + try (ResultSet rs = ps.executeQuery()) { + DeviceOperationDTO deviceSubscription; + while (rs.next()) { + deviceSubscription = new DeviceOperationDTO(); + deviceSubscription.setDeviceId(rs.getInt("DM_DEVICE_ID")); + deviceSubscription.setStatus(rs.getString("STATUS")); + deviceSubscription.setOperationId(rs.getInt("OPERATION_ID")); + deviceSubscription.setActionTriggeredFrom(rs.getString("ACTION_TRIGGERED_FROM")); + deviceSubscription.setActionTriggeredAt(rs.getTimestamp("ACTION_TRIGGERED_AT")); + deviceSubscription.setAppReleaseId(rs.getInt("AP_APP_RELEASE_ID")); + + deviceSubscriptions.add(deviceSubscription); + } + } + } + return deviceSubscriptions; + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get device subscriptions for the given AppReleaseID and DeviceID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting device subscriptions for the given AppReleaseID and DeviceID."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getSubscriptionDetailsByDeviceIds(int appReleaseId, boolean unsubscribe, int tenantId, List deviceIds) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting device subscriptions for the application release id " + appReleaseId + + " and device ids " + deviceIds + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP"; + String sql = "SELECT " + + "DS.ID AS ID, " + + "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, " + + "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, " + + "DS.UNSUBSCRIBED AS IS_UNSUBSCRIBED, " + + "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, " + + "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, " + + "DS.ACTION_TRIGGERED_FROM AS ACTION_TRIGGERED_FROM, " + + "DS.STATUS AS STATUS, " + + "DS.DM_DEVICE_ID AS DEVICE_ID " + + "FROM AP_DEVICE_SUBSCRIPTION DS " + + "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.UNSUBSCRIBED = ? AND DS.TENANT_ID = ? AND DS.DM_DEVICE_ID IN (" + + deviceIds.stream().map(id -> "?").collect(Collectors.joining(",")) + ") " + + "ORDER BY " + subscriptionStatusTime + " DESC"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setBoolean(2, unsubscribe); + ps.setInt(3, tenantId); + for (int i = 0; i < deviceIds.size(); i++) { + ps.setInt(4 + i, deviceIds.get(i)); + } + try (ResultSet rs = ps.executeQuery()) { + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved device subscriptions for application release id " + + appReleaseId + " and device ids " + deviceIds); + } + List subscriptions = new ArrayList<>(); + while (rs.next()) { + DeviceSubscriptionDTO subscription = new DeviceSubscriptionDTO(); + subscription.setId(rs.getInt("ID")); + subscription.setSubscribedBy(rs.getString("SUBSCRIBED_BY")); + subscription.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_AT")); + subscription.setUnsubscribed(rs.getBoolean("IS_UNSUBSCRIBED")); + subscription.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY")); + subscription.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_AT")); + subscription.setActionTriggeredFrom(rs.getString("ACTION_TRIGGERED_FROM")); + subscription.setStatus(rs.getString("STATUS")); + subscription.setDeviceId(rs.getInt("DEVICE_ID")); + subscriptions.add(subscription); + } + return subscriptions; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get device subscription data for application ID: " + appReleaseId + + " and device ids: " + deviceIds + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting device subscriptions for " + + "application Id: " + appReleaseId + " and device ids: " + deviceIds + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + + } + + @Override + public List getAllSubscriptionsDetails(int appReleaseId, boolean unsubscribe, int tenantId, + int offset, int limit) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting device subscriptions for the application release id " + appReleaseId + + " from the database"); + } + + String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP"; + String sql = "SELECT " + + "DS.ID AS ID, " + + "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, " + + "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, " + + "DS.UNSUBSCRIBED AS IS_UNSUBSCRIBED, " + + "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, " + + "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, " + + "DS.ACTION_TRIGGERED_FROM AS ACTION_TRIGGERED_FROM, " + + "DS.STATUS AS STATUS," + + "DS.DM_DEVICE_ID AS DEVICE_ID " + + "FROM AP_DEVICE_SUBSCRIPTION DS " + + "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.UNSUBSCRIBED = ? AND DS.TENANT_ID=? " + + "ORDER BY " + subscriptionStatusTime + " DESC " + + "LIMIT ? OFFSET ?"; + + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setBoolean(2, unsubscribe); + ps.setInt(3, tenantId); + ps.setInt(4, limit); + ps.setInt(5, offset); + try (ResultSet rs = ps.executeQuery()) { + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved device subscriptions for application release id " + + appReleaseId); + } + List deviceSubscriptions = new ArrayList<>(); + + while (rs.next()) { + DeviceSubscriptionDTO subscription = new DeviceSubscriptionDTO(); + subscription.setId(rs.getInt("ID")); + subscription.setSubscribedBy(rs.getString("SUBSCRIBED_BY")); + subscription.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_AT")); + subscription.setUnsubscribed(rs.getBoolean("IS_UNSUBSCRIBED")); + subscription.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY")); + subscription.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_AT")); + subscription.setActionTriggeredFrom(rs.getString("ACTION_TRIGGERED_FROM")); + subscription.setStatus(rs.getString("STATUS")); + subscription.setDeviceId(rs.getInt("DEVICE_ID")); + + deviceSubscriptions.add(subscription); + } + return deviceSubscriptions; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting device subscription for " + + "application Id: " + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while while running SQL to get device subscription data for application ID: " + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getAllSubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting all subscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_DEVICE_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = FALSE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get all subscriptions count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting all subscriptions count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getAllUnsubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting all unsubscription count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_DEVICE_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = TRUE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get all unsubscription count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting all unsubscription count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getDeviceSubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting device subscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_DEVICE_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = FALSE " + + "AND ACTION_TRIGGERED_FROM = 'DEVICE'"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get device subscriptions count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting device subscriptions count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getDeviceUnsubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting device unsubscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_DEVICE_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = TRUE " + + "AND ACTION_TRIGGERED_FROM = 'DEVICE'"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get device unsubscription count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting device unsubscription count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getGroupSubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting group subscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_GROUP_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = FALSE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get group subscriptions count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting group subscriptions count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getGroupUnsubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting group unsubscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_GROUP_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = TRUE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get group unsubscription count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting group unsubscription count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getRoleSubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting role subscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_ROLE_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = FALSE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get role subscriptions count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting role subscriptions count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getRoleUnsubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting role unsubscription count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_ROLE_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = TRUE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get role unsubscription count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting role unsubscription count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getUserSubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting user subscriptions count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_USER_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = FALSE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get user subscriptions count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting user subscriptions count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int getUserUnsubscriptionCount(int appReleaseId, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting user unsubscription count for the application appReleaseId " + appReleaseId + + " from the database"); + } + try { + Connection conn = this.getDBConnection(); + String sql = "SELECT COUNT(*) AS count " + + "FROM AP_USER_SUBSCRIPTION " + + "WHERE AP_APP_RELEASE_ID = ? " + + "AND TENANT_ID = ? " + + "AND UNSUBSCRIBED = TRUE"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + } + } catch (SQLException e) { + String msg = "Error occurred while running SQL to get user unsubscription count for application appReleaseId: " + + appReleaseId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection for getting user unsubscription count for appReleaseId: " + + appReleaseId + "."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/SubscriptionManagerImpl.java index 71dab6fb65..623c3b6aa9 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -19,24 +19,50 @@ package io.entgra.device.mgt.core.application.mgt.core.impl; import com.google.gson.Gson; +import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstallResponse; +import io.entgra.device.mgt.core.application.mgt.common.ApplicationSubscriptionInfo; +import io.entgra.device.mgt.core.application.mgt.common.ApplicationType; +import io.entgra.device.mgt.core.application.mgt.common.CategorizedSubscriptionResult; +import io.entgra.device.mgt.core.application.mgt.common.DeviceSubscriptionData; +import io.entgra.device.mgt.core.application.mgt.common.dto.CategorizedSubscriptionCountsDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.SubscriptionsDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceOperationDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceSubscriptionResponseDTO; +import io.entgra.device.mgt.core.application.mgt.common.DeviceTypes; +import io.entgra.device.mgt.core.application.mgt.common.ExecutionStatus; +import io.entgra.device.mgt.core.application.mgt.common.SubAction; +import io.entgra.device.mgt.core.application.mgt.common.SubscribingDeviceIdHolder; +import io.entgra.device.mgt.core.application.mgt.common.SubscriptionType; +import io.entgra.device.mgt.core.application.mgt.common.dto.GroupSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationReleaseDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.ScheduledSubscriptionDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationDTO; +import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationPolicyDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO; import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO; import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager; +import io.entgra.device.mgt.core.application.mgt.core.dao.ApplicationReleaseDAO; import io.entgra.device.mgt.core.application.mgt.core.dao.VppApplicationDAO; import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException; +import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; +import io.entgra.device.mgt.core.device.mgt.common.PaginationResult; +import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.GroupDetailsDTO; import io.entgra.device.mgt.core.device.mgt.core.DeviceManagementConstants; import io.entgra.device.mgt.core.application.mgt.core.exception.UnexpectedServerErrorException; +import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; import io.entgra.device.mgt.core.device.mgt.extensions.logger.spi.EntgraLogger; import io.entgra.device.mgt.core.notification.logger.AppInstallLogContext; import io.entgra.device.mgt.core.notification.logger.impl.EntgraAppInstallLoggerImpl; -import org.apache.commons.httpclient.HttpClient; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @@ -45,20 +71,7 @@ import org.json.JSONArray; import org.json.JSONObject; import io.entgra.device.mgt.core.apimgt.application.extension.dto.ApiApplicationKey; import io.entgra.device.mgt.core.apimgt.application.extension.exception.APIManagerException; -import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstallResponse; -import io.entgra.device.mgt.core.application.mgt.common.ApplicationSubscriptionInfo; -import io.entgra.device.mgt.core.application.mgt.common.ApplicationType; -import io.entgra.device.mgt.core.application.mgt.common.DeviceSubscriptionData; -import io.entgra.device.mgt.core.application.mgt.common.DeviceTypes; -import io.entgra.device.mgt.core.application.mgt.common.ExecutionStatus; -import io.entgra.device.mgt.core.application.mgt.common.SubAction; -import io.entgra.device.mgt.core.application.mgt.common.SubscribingDeviceIdHolder; -import io.entgra.device.mgt.core.application.mgt.common.SubscriptionType; -import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationDTO; -import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationPolicyDTO; -import io.entgra.device.mgt.core.application.mgt.common.dto.ApplicationReleaseDTO; -import io.entgra.device.mgt.core.application.mgt.common.dto.DeviceSubscriptionDTO; -import io.entgra.device.mgt.core.application.mgt.common.dto.ScheduledSubscriptionDTO; +import org.wso2.carbon.context.PrivilegedCarbonContext; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; import io.entgra.device.mgt.core.application.mgt.common.exception.DBConnectionException; import io.entgra.device.mgt.core.application.mgt.common.exception.LifecycleManagementException; @@ -83,8 +96,6 @@ import io.entgra.device.mgt.core.device.mgt.common.Device; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo; import io.entgra.device.mgt.core.device.mgt.common.MDMAppConstants; -import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; -import io.entgra.device.mgt.core.device.mgt.common.PaginationResult; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.MobileAppTypes; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.android.CustomApplication; @@ -103,12 +114,8 @@ import io.entgra.device.mgt.core.device.mgt.core.util.MDMAndroidOperationUtil; import io.entgra.device.mgt.core.device.mgt.core.util.MDMIOSOperationUtil; import io.entgra.device.mgt.core.device.mgt.core.util.MDMWindowsOperationUtil; import io.entgra.device.mgt.core.identity.jwt.client.extension.dto.AccessTokenInfo; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethodBase; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.StringRequestEntity; -import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.api.UserStoreManager; import javax.ws.rs.core.MediaType; import java.io.BufferedReader; @@ -125,6 +132,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -132,6 +140,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -143,12 +152,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager { private SubscriptionDAO subscriptionDAO; private ApplicationDAO applicationDAO; private VppApplicationDAO vppApplicationDAO; + private ApplicationReleaseDAO applicationReleaseDAO; private LifecycleStateManager lifecycleStateManager; public SubscriptionManagerImpl() { this.lifecycleStateManager = DataHolder.getInstance().getLifecycleStateManager(); this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO(); this.applicationDAO = ApplicationManagementDAOFactory.getApplicationDAO(); + this.applicationReleaseDAO = ApplicationManagementDAOFactory.getApplicationReleaseDAO(); this.vppApplicationDAO = ApplicationManagementDAOFactory.getVppApplicationDAO(); } @@ -1542,16 +1553,19 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } @Override - public PaginationResult getAppSubscriptionDetails(PaginationRequest request, String appUUID, String actionStatus, - String action, String installedVersion) throws ApplicationManagementException { + public CategorizedSubscriptionResult getAppSubscriptionDetails(PaginationRequest request, String appUUID, String actionStatus, + String action, String installedVersion) throws ApplicationManagementException { int limitValue = request.getRowCount(); int offsetValue = request.getStartIndex(); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - DeviceManagementProviderService deviceManagementProviderService = HelperUtil - .getDeviceManagementProviderService(); + DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); + List installedDevices = new ArrayList<>(); + List pendingDevices = new ArrayList<>(); + List errorDevices = new ArrayList<>(); + if (offsetValue < 0 || limitValue <= 0) { - String msg = "Found incompatible values for offset and limit. Hence please check the request and resend. " - + "Offset " + offsetValue + " limit " + limitValue; + String msg = "Found incompatible values for offset and limit. Hence please check the request and resend. " + + "Offset " + offsetValue + " limit " + limitValue; log.error(msg); throw new BadRequestException(msg); } @@ -1569,31 +1583,26 @@ public class SubscriptionManagerImpl implements SubscriptionManager { List deviceSubscriptionDTOS = subscriptionDAO .getDeviceSubscriptions(applicationReleaseId, tenantId, actionStatus, action); if (deviceSubscriptionDTOS.isEmpty()) { - PaginationResult paginationResult = new PaginationResult(); - paginationResult.setData(new ArrayList<>()); - paginationResult.setRecordsFiltered(0); - paginationResult.setRecordsTotal(0); - return paginationResult; + return new CategorizedSubscriptionResult(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); } List deviceIdList = deviceSubscriptionDTOS.stream().map(DeviceSubscriptionDTO::getDeviceId) .collect(Collectors.toList()); - Map currentVersionsMap = subscriptionDAO.getCurrentInstalledAppVersion(applicationDTO.getId(),deviceIdList, installedVersion); + Map currentVersionsMap = + subscriptionDAO.getCurrentInstalledAppVersion(applicationDTO.getId(), deviceIdList, installedVersion); try { - //pass the device id list to device manager service method - PaginationResult paginationResult = deviceManagementProviderService.getAppSubscribedDevices - (request, deviceIdList); - List deviceSubscriptionDataList = new ArrayList<>(); + // Pass the device id list to device manager service method + PaginationResult paginationResult = deviceManagementProviderService.getAppSubscribedDevices(request, deviceIdList); if (!paginationResult.getData().isEmpty()) { List devices = (List) paginationResult.getData(); for (Device device : devices) { - if(installedVersion != null && !installedVersion.isEmpty() && !currentVersionsMap.containsKey(device.getId())){ + if (installedVersion != null && !installedVersion.isEmpty() && !currentVersionsMap.containsKey(device.getId())) { continue; } DeviceSubscriptionData deviceSubscriptionData = new DeviceSubscriptionData(); - if(currentVersionsMap.containsKey(device.getId())){ + if (currentVersionsMap.containsKey(device.getId())) { deviceSubscriptionData.setCurrentInstalledVersion(currentVersionsMap.get(device.getId())); - }else{ + } else { deviceSubscriptionData.setCurrentInstalledVersion("-"); } for (DeviceSubscriptionDTO subscription : deviceSubscriptionDTOS) { @@ -1602,39 +1611,51 @@ public class SubscriptionManagerImpl implements SubscriptionManager { if (subscription.isUnsubscribed()) { deviceSubscriptionData.setAction(Constants.UNSUBSCRIBED); deviceSubscriptionData.setActionTriggeredBy(subscription.getUnsubscribedBy()); - deviceSubscriptionData - .setActionTriggeredTimestamp(subscription.getUnsubscribedTimestamp().getTime() / 1000); + deviceSubscriptionData.setActionTriggeredTimestamp(subscription.getUnsubscribedTimestamp()); } else { deviceSubscriptionData.setAction(Constants.SUBSCRIBED); deviceSubscriptionData.setActionTriggeredBy(subscription.getSubscribedBy()); - deviceSubscriptionData - .setActionTriggeredTimestamp(subscription.getSubscribedTimestamp().getTime() / 1000); + deviceSubscriptionData.setActionTriggeredTimestamp(subscription.getSubscribedTimestamp()); } deviceSubscriptionData.setActionType(subscription.getActionTriggeredFrom()); deviceSubscriptionData.setStatus(subscription.getStatus()); deviceSubscriptionData.setSubId(subscription.getId()); - deviceSubscriptionDataList.add(deviceSubscriptionData); + + // Categorize the subscription data based on its status + switch (subscription.getStatus()) { + case "COMPLETED": + installedDevices.add(deviceSubscriptionData); + break; + case "ERROR": + case "INVALID": + case "UNAUTHORIZED": + errorDevices.add(deviceSubscriptionData); + break; + case "IN_PROGRESS": + case "PENDING": + case "REPEATED": + pendingDevices.add(deviceSubscriptionData); + break; + } break; } } } } - paginationResult.setData(deviceSubscriptionDataList); - return paginationResult; + return new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices); } catch (DeviceManagementException e) { - String msg = "service error occurred while getting device data from the device management service. " - + "Device ids " + deviceIdList; + String msg = "Service error occurred while getting device data from the device management service. " + + "Device ids " + deviceIdList; log.error(msg, e); throw new ApplicationManagementException(msg, e); } } catch (ApplicationManagementDAOException e) { - String msg = - "Error occurred when getting application release data for application release UUID: " + appUUID; + String msg = "Error occurred when getting application release data for application release UUID: " + appUUID; log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (DBConnectionException e) { - String msg = "DB Connection error occurred while trying to get subscription data of application which has " - + "application release UUID " + appUUID; + String msg = "DB Connection error occurred while trying to get subscription data of application which has " + + "application release UUID " + appUUID; log.error(msg, e); throw new ApplicationManagementException(msg, e); } finally { @@ -1712,4 +1733,1016 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } } + @Override + public List getGroupsSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, + int limit) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); + String groupName; + String status; + + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = this.applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + List groupDetailsWithDevices = new ArrayList<>(); + + List groupDetails = + subscriptionDAO.getGroupsSubscriptionDetailsByAppReleaseID(appReleaseId, unsubscribe, tenantId, offset, limit); + if (groupDetails == null) { + throw new ApplicationManagementException("Group details not found for appReleaseId: " + appReleaseId); + } + + GroupManagementProviderService groupManagementProviderService = HelperUtil.getGroupManagementProviderService(); + + for (GroupSubscriptionDTO groupDetail : groupDetails) { + groupName = groupDetail.getGroupName(); + + // Retrieve group details and device IDs for the group using the service layer + GroupDetailsDTO groupDetailWithDevices = + groupManagementProviderService.getGroupDetailsWithDevices(groupName, offset, limit); + + SubscriptionsDTO groupDetailDTO = new SubscriptionsDTO(); + groupDetailDTO.setId(groupDetailWithDevices.getGroupId()); + groupDetailDTO.setName(groupDetail.getGroupName()); + groupDetailDTO.setOwner(groupDetailWithDevices.getGroupOwner()); + groupDetailDTO.setSubscribedBy(groupDetail.getSubscribedBy()); + groupDetailDTO.setSubscribedTimestamp(groupDetail.getSubscribedTimestamp()); + groupDetailDTO.setUnsubscribed(groupDetail.isUnsubscribed()); + groupDetailDTO.setUnsubscribedBy(groupDetail.getUnsubscribedBy()); + groupDetailDTO.setUnsubscribedTimestamp(groupDetail.getUnsubscribedTimestamp()); + groupDetailDTO.setAppReleaseId(groupDetail.getAppReleaseId()); + groupDetailDTO.setDeviceCount(groupDetailWithDevices.getDeviceCount()); + + // Fetch device subscriptions for each device ID in the group + List pendingDevices = new ArrayList<>(); + List installedDevices = new ArrayList<>(); + List errorDevices = new ArrayList<>(); + List newDevices = new ArrayList<>(); + List subscribedDevices = new ArrayList<>(); + + List deviceIds = groupDetailWithDevices.getDeviceIds(); + Map statusCounts = new HashMap<>(); + statusCounts.put("PENDING", 0); + statusCounts.put("COMPLETED", 0); + statusCounts.put("ERROR", 0); + statusCounts.put("NEW", 0); + statusCounts.put("SUBSCRIBED", 0); + + // Get subscribed devices if unsubscribed devices are requested + List subscribedDeviceSubscriptions = new ArrayList<>(); + if (unsubscribe) { + subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( + appReleaseId, !unsubscribe, tenantId, deviceIds); + } + + for (Integer deviceId : deviceIds) { + List deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( + groupDetail.getAppReleaseId(), unsubscribe, tenantId, deviceIds); + boolean isNewDevice = true; + for (DeviceSubscriptionDTO subscription : deviceSubscriptions) { + if (subscription.getDeviceId() == deviceId) { + DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); + deviceDetail.setDeviceId(subscription.getDeviceId()); + deviceDetail.setStatus(subscription.getStatus()); + deviceDetail.setActionType(subscription.getActionTriggeredFrom()); + deviceDetail.setDeviceOwner(groupDetailWithDevices.getDeviceOwners().get(deviceId)); + deviceDetail.setDeviceStatus(groupDetailWithDevices.getDeviceStatuses().get(deviceId)); + deviceDetail.setDeviceName(groupDetailWithDevices.getDeviceNames().get(deviceId)); + deviceDetail.setSubId(subscription.getId()); + deviceDetail.setActionTriggeredBy(subscription.getSubscribedBy()); + deviceDetail.setActionTriggeredTimestamp(subscription.getSubscribedTimestamp()); + deviceDetail.setUnsubscribed(subscription.isUnsubscribed()); + deviceDetail.setUnsubscribedBy(subscription.getUnsubscribedBy()); + deviceDetail.setUnsubscribedTimestamp(subscription.getUnsubscribedTimestamp()); + deviceDetail.setType(groupDetailWithDevices.getDeviceTypes().get(deviceId)); + deviceDetail.setDeviceIdentifier(groupDetailWithDevices.getDeviceIdentifiers().get(deviceId)); + + status = subscription.getStatus(); + switch (status) { + case "COMPLETED": + installedDevices.add(deviceDetail); + statusCounts.put("COMPLETED", statusCounts.get("COMPLETED") + 1); + break; + case "ERROR": + case "INVALID": + case "UNAUTHORIZED": + errorDevices.add(deviceDetail); + statusCounts.put("ERROR", statusCounts.get("ERROR") + 1); + break; + case "IN_PROGRESS": + case "PENDING": + case "REPEATED": + pendingDevices.add(deviceDetail); + statusCounts.put("PENDING", statusCounts.get("PENDING") + 1); + break; + } + isNewDevice = false; + } + } + if (isNewDevice) { + boolean isSubscribedDevice = false; + for (DeviceSubscriptionDTO subscribedDevice : subscribedDeviceSubscriptions) { + if (subscribedDevice.getDeviceId() == deviceId) { + DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); + subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId()); + subscribedDeviceDetail.setDeviceOwner(groupDetailWithDevices.getDeviceOwners().get(deviceId)); + subscribedDeviceDetail.setDeviceStatus(groupDetailWithDevices.getDeviceStatuses().get(deviceId)); + subscribedDeviceDetail.setDeviceName(groupDetailWithDevices.getDeviceNames().get(deviceId)); + subscribedDeviceDetail.setSubId(subscribedDevice.getId()); + subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy()); + subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp()); + subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom()); + subscribedDeviceDetail.setStatus(subscribedDevice.getStatus()); + subscribedDeviceDetail.setType(groupDetailWithDevices.getDeviceTypes().get(deviceId)); + subscribedDeviceDetail.setDeviceIdentifier(groupDetailWithDevices.getDeviceIdentifiers().get(deviceId)); + subscribedDevices.add(subscribedDeviceDetail); + statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1); + isSubscribedDevice = true; + break; + } + } + if (!isSubscribedDevice) { + DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); + newDeviceDetail.setDeviceId(deviceId); + newDeviceDetail.setDeviceOwner(groupDetailWithDevices.getDeviceOwners().get(deviceId)); + newDeviceDetail.setDeviceStatus(groupDetailWithDevices.getDeviceStatuses().get(deviceId)); + newDeviceDetail.setDeviceName(groupDetailWithDevices.getDeviceNames().get(deviceId)); + newDeviceDetail.setType(groupDetailWithDevices.getDeviceTypes().get(deviceId)); + newDeviceDetail.setDeviceIdentifier(groupDetailWithDevices.getDeviceIdentifiers().get(deviceId)); + newDevices.add(newDeviceDetail); + statusCounts.put("NEW", statusCounts.get("NEW") + 1); + } + } + } + + int totalDevices = deviceIds.size(); + Map statusPercentages = new HashMap<>(); + for (Map.Entry entry : statusCounts.entrySet()) { + double percentage = ((double) entry.getValue() / totalDevices) * 100; + String formattedPercentage = String.format("%.2f", percentage); + statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); + } + + CategorizedSubscriptionResult categorizedSubscriptionResult; + if (subscribedDevices.isEmpty()) { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); + } else { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); + } + groupDetailDTO.setDevices(categorizedSubscriptionResult); + groupDetailDTO.setStatusPercentages(statusPercentages); + + groupDetailsWithDevices.add(groupDetailDTO); + } + + return groupDetailsWithDevices; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while fetching groups and devices for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "DB Connection error occurred while fetching groups and devices for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (GroupManagementException e) { + String msg = "Error occurred while fetching group details and device IDs: " + e.getMessage(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public List getUserSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); + String userName; + String status; + + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = this.applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + List userSubscriptionsWithDevices = new ArrayList<>(); + + List userSubscriptions = + subscriptionDAO.getUserSubscriptionsByAppReleaseID(appReleaseId, unsubscribe, tenantId, offset, limit); + if (userSubscriptions == null) { + throw new ApplicationManagementException("User details not found for appReleaseId: " + appReleaseId); + } + + DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); + + for (SubscriptionsDTO userSubscription : userSubscriptions) { + userName = userSubscription.getName(); + + // Retrieve owner details and device IDs for the user using the service layer + OwnerWithDeviceDTO ownerDetailsWithDevices = + deviceManagementProviderService.getOwnersWithDeviceIds(userName); + + SubscriptionsDTO userSubscriptionDTO = new SubscriptionsDTO(); + userSubscriptionDTO.setName(userSubscription.getName()); + userSubscriptionDTO.setSubscribedBy(userSubscription.getSubscribedBy()); + userSubscriptionDTO.setSubscribedTimestamp(userSubscription.getSubscribedTimestamp()); + userSubscriptionDTO.setUnsubscribed(userSubscription.getUnsubscribed()); + userSubscriptionDTO.setUnsubscribedBy(userSubscription.getUnsubscribedBy()); + userSubscriptionDTO.setUnsubscribedTimestamp(userSubscription.getUnsubscribedTimestamp()); + userSubscriptionDTO.setAppReleaseId(userSubscription.getAppReleaseId()); + + userSubscriptionDTO.setDeviceCount(ownerDetailsWithDevices.getDeviceCount()); + + // Fetch device subscriptions for each device ID associated with the user + List pendingDevices = new ArrayList<>(); + List installedDevices = new ArrayList<>(); + List errorDevices = new ArrayList<>(); + List newDevices = new ArrayList<>(); + List subscribedDevices = new ArrayList<>(); + + List deviceIds = ownerDetailsWithDevices.getDeviceIds(); + Map statusCounts = new HashMap<>(); + statusCounts.put("PENDING", 0); + statusCounts.put("COMPLETED", 0); + statusCounts.put("ERROR", 0); + statusCounts.put("NEW", 0); + statusCounts.put("SUBSCRIBED", 0); + + List subscribedDeviceSubscriptions = new ArrayList<>(); + if (unsubscribe) { + subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( + appReleaseId, !unsubscribe, tenantId, deviceIds); + } + + for (Integer deviceId : deviceIds) { + List deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( + userSubscription.getAppReleaseId(), unsubscribe, tenantId, deviceIds); + boolean isNewDevice = true; + for (DeviceSubscriptionDTO subscription : deviceSubscriptions) { + if (subscription.getDeviceId() == deviceId) { + DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); + deviceDetail.setDeviceId(subscription.getDeviceId()); + deviceDetail.setSubId(subscription.getId()); + deviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); + deviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); + deviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); + deviceDetail.setActionType(subscription.getActionTriggeredFrom()); + deviceDetail.setStatus(subscription.getStatus()); + deviceDetail.setActionType(subscription.getActionTriggeredFrom()); + deviceDetail.setActionTriggeredBy(subscription.getSubscribedBy()); + deviceDetail.setActionTriggeredTimestamp(subscription.getSubscribedTimestamp()); + deviceDetail.setUnsubscribed(subscription.isUnsubscribed()); + deviceDetail.setUnsubscribedBy(subscription.getUnsubscribedBy()); + deviceDetail.setUnsubscribedTimestamp(subscription.getUnsubscribedTimestamp()); + deviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); + deviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); + + status = subscription.getStatus(); + switch (status) { + case "COMPLETED": + installedDevices.add(deviceDetail); + statusCounts.put("COMPLETED", statusCounts.get("COMPLETED") + 1); + break; + case "ERROR": + case "INVALID": + case "UNAUTHORIZED": + errorDevices.add(deviceDetail); + statusCounts.put("ERROR", statusCounts.get("ERROR") + 1); + break; + case "IN_PROGRESS": + case "PENDING": + case "REPEATED": + pendingDevices.add(deviceDetail); + statusCounts.put("PENDING", statusCounts.get("PENDING") + 1); + break; + } + isNewDevice = false; + } + } + if (isNewDevice) { + boolean isSubscribedDevice = false; + for (DeviceSubscriptionDTO subscribedDevice : subscribedDeviceSubscriptions) { + if (subscribedDevice.getDeviceId() == deviceId) { + DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); + subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId()); + subscribedDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); + subscribedDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); + subscribedDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); + subscribedDeviceDetail.setSubId(subscribedDevice.getId()); + subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy()); + subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp()); + subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom()); + subscribedDeviceDetail.setStatus(subscribedDevice.getStatus()); + subscribedDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); + subscribedDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); + subscribedDevices.add(subscribedDeviceDetail); + statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1); + isSubscribedDevice = true; + break; + } + } + if (!isSubscribedDevice) { + DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); + newDeviceDetail.setDeviceId(deviceId); + newDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); + newDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); + newDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); + newDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); + newDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); + newDevices.add(newDeviceDetail); + statusCounts.put("NEW", statusCounts.get("NEW") + 1); + } + } + } + + int totalDevices = deviceIds.size(); + Map statusPercentages = new HashMap<>(); + for (Map.Entry entry : statusCounts.entrySet()) { + double percentage = ((double) entry.getValue() / totalDevices) * 100; + String formattedPercentage = String.format("%.2f", percentage); + statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); + } + + CategorizedSubscriptionResult categorizedSubscriptionResult; + if (subscribedDevices.isEmpty()) { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); + } else { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); + } + userSubscriptionDTO.setDevices(categorizedSubscriptionResult); + userSubscriptionDTO.setStatusPercentages(statusPercentages); + + userSubscriptionsWithDevices.add(userSubscriptionDTO); + } + + return userSubscriptionsWithDevices; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while getting user subscriptions for the application release UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "DB Connection error occurred while getting user subscriptions for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DeviceManagementDAOException e) { + throw new RuntimeException(e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public List getRoleSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); + String roleName; + String status; + + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = this.applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + List roleSubscriptionsWithDevices = new ArrayList<>(); + + List roleSubscriptions = + subscriptionDAO.getRoleSubscriptionsByAppReleaseID(appReleaseId, unsubscribe, tenantId, offset, limit); + if (roleSubscriptions == null) { + throw new ApplicationManagementException("Role details not found for appReleaseId: " + appReleaseId); + } + + DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); + + for (SubscriptionsDTO roleSubscription : roleSubscriptions) { + roleName = roleSubscription.getName(); + + SubscriptionsDTO roleSubscriptionDTO = new SubscriptionsDTO(); + roleSubscriptionDTO.setName(roleSubscription.getName()); + roleSubscriptionDTO.setSubscribedBy(roleSubscription.getSubscribedBy()); + roleSubscriptionDTO.setSubscribedTimestamp(roleSubscription.getSubscribedTimestamp()); + roleSubscriptionDTO.setUnsubscribed(roleSubscription.getUnsubscribed()); + roleSubscriptionDTO.setUnsubscribedBy(roleSubscription.getUnsubscribedBy()); + roleSubscriptionDTO.setUnsubscribedTimestamp(roleSubscription.getUnsubscribedTimestamp()); + roleSubscriptionDTO.setAppReleaseId(roleSubscription.getAppReleaseId()); + + List pendingDevices = new ArrayList<>(); + List installedDevices = new ArrayList<>(); + List errorDevices = new ArrayList<>(); + List newDevices = new ArrayList<>(); + List subscribedDevices = new ArrayList<>(); + + Map statusCounts = new HashMap<>(); + statusCounts.put("PENDING", 0); + statusCounts.put("COMPLETED", 0); + statusCounts.put("ERROR", 0); + statusCounts.put("NEW", 0); + statusCounts.put("SUBSCRIBED", 0); + + List users = this.getUsersForRole(roleName); + + for (String user : users) { + OwnerWithDeviceDTO ownerDetailsWithDevices; + try { + ownerDetailsWithDevices = deviceManagementProviderService.getOwnersWithDeviceIds(user); + } catch (DeviceManagementDAOException e) { + throw new ApplicationManagementException("Error retrieving owner details with devices for user: " + user, e); + } + + List deviceIds = ownerDetailsWithDevices.getDeviceIds(); + for (Integer deviceId : deviceIds) { + + List subscribedDeviceSubscriptions = new ArrayList<>(); + if (unsubscribe) { + subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( + appReleaseId, !unsubscribe, tenantId, deviceIds); + } + + List deviceSubscriptions; + try { + deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( + roleSubscription.getAppReleaseId(), unsubscribe, tenantId, deviceIds); + } catch (ApplicationManagementDAOException e) { + throw new ApplicationManagementException("Error retrieving device subscriptions", e); + } + + boolean isNewDevice = true; + for (DeviceSubscriptionDTO deviceSubscription : deviceSubscriptions) { + if (deviceSubscription.getDeviceId() == deviceId) { + DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); + deviceDetail.setDeviceId(deviceSubscription.getDeviceId()); + deviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); + deviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); + deviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); + deviceDetail.setActionType(deviceSubscription.getActionTriggeredFrom()); + deviceDetail.setStatus(deviceSubscription.getStatus()); + deviceDetail.setActionType(deviceSubscription.getActionTriggeredFrom()); + deviceDetail.setActionTriggeredBy(deviceSubscription.getSubscribedBy()); + deviceDetail.setSubId(deviceSubscription.getId()); + deviceDetail.setActionTriggeredTimestamp(deviceSubscription.getSubscribedTimestamp()); + deviceDetail.setUnsubscribed(deviceSubscription.isUnsubscribed()); + deviceDetail.setUnsubscribedBy(deviceSubscription.getUnsubscribedBy()); + deviceDetail.setUnsubscribedTimestamp(deviceSubscription.getUnsubscribedTimestamp()); + deviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); + deviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); + + status = deviceSubscription.getStatus(); + switch (status) { + case "COMPLETED": + installedDevices.add(deviceDetail); + statusCounts.put("COMPLETED", statusCounts.get("COMPLETED") + 1); + break; + case "ERROR": + case "INVALID": + case "UNAUTHORIZED": + errorDevices.add(deviceDetail); + statusCounts.put("ERROR", statusCounts.get("ERROR") + 1); + break; + case "IN_PROGRESS": + case "PENDING": + case "REPEATED": + pendingDevices.add(deviceDetail); + statusCounts.put("PENDING", statusCounts.get("PENDING") + 1); + break; + } + isNewDevice = false; + } + } + if (isNewDevice) { + boolean isSubscribedDevice = false; + for (DeviceSubscriptionDTO subscribedDevice : subscribedDeviceSubscriptions) { + if (subscribedDevice.getDeviceId() == deviceId) { + DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); + subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId()); + subscribedDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); + subscribedDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); + subscribedDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); + subscribedDeviceDetail.setSubId(subscribedDevice.getId()); + subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy()); + subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp()); + subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom()); + subscribedDeviceDetail.setStatus(subscribedDevice.getStatus()); + subscribedDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); + subscribedDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); + subscribedDevices.add(subscribedDeviceDetail); + statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1); + isSubscribedDevice = true; + break; + } + } + if (!isSubscribedDevice) { + DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); + newDeviceDetail.setDeviceId(deviceId); + newDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); + newDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); + newDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); + newDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); + newDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); + newDevices.add(newDeviceDetail); + statusCounts.put("NEW", statusCounts.get("NEW") + 1); + } + } + } + } + + int totalDevices = + pendingDevices.size() + installedDevices.size() + errorDevices.size() + newDevices.size() + subscribedDevices.size(); + Map statusPercentages = new HashMap<>(); + for (Map.Entry entry : statusCounts.entrySet()) { + double percentage = totalDevices == 0 ? 0.0 : ((double) entry.getValue() / totalDevices) * 100; + String formattedPercentage = String.format("%.2f", percentage); + statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); + } + + CategorizedSubscriptionResult categorizedSubscriptionResult; + if (subscribedDevices.isEmpty()) { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); + } else { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); + } + roleSubscriptionDTO.setDevices(categorizedSubscriptionResult); + roleSubscriptionDTO.setStatusPercentages(statusPercentages); + roleSubscriptionDTO.setDeviceCount(totalDevices); + + roleSubscriptionsWithDevices.add(roleSubscriptionDTO); + } + + return roleSubscriptionsWithDevices; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred in retrieving role subscriptions with devices"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while retrieving the database connection"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (UserStoreException e) { + String msg = "Error occurred while retrieving users for role"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + // Get user list for each role + public List getUsersForRole(String roleName) throws UserStoreException { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + int tenantId = ctx.getTenantId(); + UserStoreManager userStoreManager = DataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId).getUserStoreManager(); + String[] users = userStoreManager.getUserListOfRole(roleName); + return Arrays.asList(users); + } + + @Override + public DeviceSubscriptionResponseDTO getDeviceSubscriptionsDetailsByUUID(String uuid, String subscriptionStatus, int offset, + int limit) throws ApplicationManagementException { + + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); + + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); + List deviceSubscriptions = + subscriptionDAO.getDeviceSubscriptionsByAppReleaseID(appReleaseId, unsubscribe, tenantId, offset, limit); + + // empty response for no device subscriptions + if (deviceSubscriptions.isEmpty()) { + return new DeviceSubscriptionResponseDTO(0, Collections.emptyMap(), + new CategorizedSubscriptionResult(Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), Collections.emptyList())); + } + + List allDevices = + deviceManagementProviderService.getDevicesByTenantId(tenantId); + + List deviceIds = allDevices.stream() + .map(DeviceDetailsDTO::getDeviceId) + .collect(Collectors.toList()); + + Map statusCounts = new HashMap<>(); + statusCounts.put("PENDING", 0); + statusCounts.put("COMPLETED", 0); + statusCounts.put("ERROR", 0); + statusCounts.put("NEW", 0); + statusCounts.put("SUBSCRIBED", 0); + + List installedDevices = new ArrayList<>(); + List pendingDevices = new ArrayList<>(); + List errorDevices = new ArrayList<>(); + List newDevices = new ArrayList<>(); + List subscribedDevices = new ArrayList<>(); + + Map deviceSubscriptionMap = deviceSubscriptions.stream() + .collect(Collectors.toMap(DeviceSubscriptionDTO::getDeviceId, Function.identity())); + Map allDevicesMap = allDevices.stream() + .collect(Collectors.toMap(DeviceDetailsDTO::getDeviceId, Function.identity())); + + List allSubscriptionsForUnSubscribed = + subscriptionDAO.getSubscriptionDetailsByDeviceIds(appReleaseId, !unsubscribe, tenantId, deviceIds); + List allSubscriptionsForSubscribed = + subscriptionDAO.getSubscriptionDetailsByDeviceIds(appReleaseId, unsubscribe, tenantId, deviceIds); + Map allSubscriptionForUnSubscribedMap = allSubscriptionsForUnSubscribed.stream() + .collect(Collectors.toMap(DeviceSubscriptionDTO::getDeviceId, Function.identity())); + Map allSubscriptionForSubscribedMap = allSubscriptionsForSubscribed.stream() + .collect(Collectors.toMap(DeviceSubscriptionDTO::getDeviceId, Function.identity())); + + for (DeviceDetailsDTO device : allDevices) { + Integer deviceId = device.getDeviceId(); + OwnerWithDeviceDTO ownerWithDevice = + deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId); + if (ownerWithDevice == null) { + continue; + } + + if (deviceSubscriptionMap.containsKey(deviceId)) { + DeviceSubscriptionDTO subscription = deviceSubscriptionMap.get(deviceId); + DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); + deviceDetail.setDeviceId(subscription.getDeviceId()); + deviceDetail.setSubId(subscription.getId()); + deviceDetail.setDeviceName(ownerWithDevice.getDeviceNames()); + deviceDetail.setDeviceOwner(ownerWithDevice.getUserName()); + deviceDetail.setDeviceStatus(ownerWithDevice.getDeviceStatus()); + deviceDetail.setActionType(subscription.getActionTriggeredFrom()); + deviceDetail.setStatus(subscription.getStatus()); + deviceDetail.setActionTriggeredBy(subscription.getSubscribedBy()); + deviceDetail.setActionTriggeredTimestamp(subscription.getSubscribedTimestamp()); + deviceDetail.setUnsubscribed(subscription.isUnsubscribed()); + deviceDetail.setUnsubscribedBy(subscription.getUnsubscribedBy()); + deviceDetail.setUnsubscribedTimestamp(subscription.getUnsubscribedTimestamp()); + deviceDetail.setType(ownerWithDevice.getDeviceTypes()); + deviceDetail.setDeviceIdentifier(ownerWithDevice.getDeviceIdentifiers()); + + String status = subscription.getStatus(); + switch (status) { + case "COMPLETED": + installedDevices.add(deviceDetail); + statusCounts.put("COMPLETED", statusCounts.get("COMPLETED") + 1); + break; + case "ERROR": + case "INVALID": + case "UNAUTHORIZED": + errorDevices.add(deviceDetail); + statusCounts.put("ERROR", statusCounts.get("ERROR") + 1); + break; + case "IN_PROGRESS": + case "PENDING": + case "REPEATED": + pendingDevices.add(deviceDetail); + statusCounts.put("PENDING", statusCounts.get("PENDING") + 1); + break; + } + } else if (unsubscribe && allSubscriptionForUnSubscribedMap.containsKey(deviceId) && !deviceSubscriptionMap.containsKey(deviceId)) { + // Check if the device subscription has unsubscribed status set to false + DeviceSubscriptionDTO allSubscription = allSubscriptionForUnSubscribedMap.get(deviceId); + if (!allSubscription.isUnsubscribed()) { + DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); + subscribedDeviceDetail.setDeviceId(allSubscription.getDeviceId()); + subscribedDeviceDetail.setDeviceName(ownerWithDevice.getDeviceNames()); + subscribedDeviceDetail.setDeviceOwner(ownerWithDevice.getUserName()); + subscribedDeviceDetail.setDeviceStatus(ownerWithDevice.getDeviceStatus()); + subscribedDeviceDetail.setSubId(allSubscription.getId()); + subscribedDeviceDetail.setActionTriggeredBy(allSubscription.getSubscribedBy()); + subscribedDeviceDetail.setActionTriggeredTimestamp(allSubscription.getSubscribedTimestamp()); + subscribedDeviceDetail.setActionType(allSubscription.getActionTriggeredFrom()); + subscribedDeviceDetail.setStatus(allSubscription.getStatus()); + subscribedDeviceDetail.setType(ownerWithDevice.getDeviceTypes()); + subscribedDeviceDetail.setDeviceIdentifier(ownerWithDevice.getDeviceIdentifiers()); + subscribedDevices.add(subscribedDeviceDetail); + statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1); + } + } else if (unsubscribe && !allSubscriptionForUnSubscribedMap.containsKey(deviceId) && !deviceSubscriptionMap.containsKey(deviceId) + && (allDevicesMap.containsKey(deviceId))) { + DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); + newDeviceDetail.setDeviceId(deviceId); + newDeviceDetail.setDeviceOwner(ownerWithDevice.getUserName()); + newDeviceDetail.setDeviceStatus(ownerWithDevice.getDeviceStatus()); + newDeviceDetail.setType(ownerWithDevice.getDeviceTypes()); + newDeviceDetail.setDeviceIdentifier(ownerWithDevice.getDeviceIdentifiers()); + newDevices.add(newDeviceDetail); + statusCounts.put("NEW", statusCounts.get("NEW") + 1); + } else if (!unsubscribe && !allSubscriptionForSubscribedMap.containsKey(deviceId) && !deviceSubscriptionMap.containsKey(deviceId) + && (allDevicesMap.containsKey(deviceId))) { + DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); + newDeviceDetail.setDeviceId(deviceId); + newDeviceDetail.setDeviceName(ownerWithDevice.getDeviceNames()); + newDeviceDetail.setDeviceOwner(ownerWithDevice.getUserName()); + newDeviceDetail.setDeviceStatus(ownerWithDevice.getDeviceStatus()); + newDeviceDetail.setType(ownerWithDevice.getDeviceTypes()); + newDeviceDetail.setDeviceIdentifier(ownerWithDevice.getDeviceIdentifiers()); + newDevices.add(newDeviceDetail); + statusCounts.put("NEW", statusCounts.get("NEW") + 1); + } + } + + int totalDevices = allDevices.size(); + Map statusPercentages = new HashMap<>(); + for (Map.Entry entry : statusCounts.entrySet()) { + double percentage = ((double) entry.getValue() / totalDevices) * 100; + String formattedPercentage = String.format("%.2f", percentage); + statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); + } + + CategorizedSubscriptionResult categorizedSubscriptionResult; + if (subscribedDevices.isEmpty()) { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); + } else { + categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); + } + DeviceSubscriptionResponseDTO deviceSubscriptionResponse = + new DeviceSubscriptionResponseDTO(totalDevices, statusPercentages, categorizedSubscriptionResult); + + return deviceSubscriptionResponse; + + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while getting device subscriptions for the application release UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "DB Connection error occurred while getting device subscriptions for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DeviceManagementDAOException e) { + throw new RuntimeException(e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public DeviceSubscriptionResponseDTO getAllSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); + + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = this.applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + List allSubscriptions = + subscriptionDAO.getAllSubscriptionsDetails(appReleaseId, unsubscribe, tenantId, offset, limit); + + // empty response for no subscriptions + if (allSubscriptions.isEmpty()) { + return new DeviceSubscriptionResponseDTO(0, Collections.emptyMap(), + new CategorizedSubscriptionResult(Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), Collections.emptyList())); + } + + DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); + + Map allSubscriptionMap = allSubscriptions.stream() + .collect(Collectors.toMap(DeviceSubscriptionDTO::getDeviceId, Function.identity())); + + List pendingDevices = new ArrayList<>(); + List installedDevices = new ArrayList<>(); + List errorDevices = new ArrayList<>(); + List newDevices = new ArrayList<>(); + + Map statusCounts = new HashMap<>(); + statusCounts.put("PENDING", 0); + statusCounts.put("COMPLETED", 0); + statusCounts.put("ERROR", 0); + statusCounts.put("NEW", 0); + + List allDevices = + deviceManagementProviderService.getDevicesByTenantId(tenantId); + + for (DeviceDetailsDTO device : allDevices) { + Integer deviceId = device.getDeviceId(); + OwnerWithDeviceDTO ownerWithDevice = + deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId); + if (ownerWithDevice == null) { + continue; + } + + if (allSubscriptionMap.containsKey(deviceId)) { + DeviceSubscriptionDTO subscription = allSubscriptionMap.get(deviceId); + DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); + deviceDetail.setDeviceId(subscription.getDeviceId()); + deviceDetail.setDeviceName(ownerWithDevice.getDeviceNames()); + deviceDetail.setSubId(subscription.getId()); + deviceDetail.setDeviceOwner(ownerWithDevice.getUserName()); + deviceDetail.setDeviceStatus(ownerWithDevice.getDeviceStatus()); + deviceDetail.setActionType(subscription.getActionTriggeredFrom()); + deviceDetail.setStatus(subscription.getStatus()); + deviceDetail.setActionTriggeredBy(subscription.getSubscribedBy()); + deviceDetail.setActionTriggeredTimestamp(subscription.getSubscribedTimestamp()); + deviceDetail.setUnsubscribed(subscription.isUnsubscribed()); + deviceDetail.setUnsubscribedBy(subscription.getUnsubscribedBy()); + deviceDetail.setUnsubscribedTimestamp(subscription.getUnsubscribedTimestamp()); + deviceDetail.setType(ownerWithDevice.getDeviceTypes()); + deviceDetail.setDeviceIdentifier(ownerWithDevice.getDeviceIdentifiers()); + + String status = subscription.getStatus(); + switch (status) { + case "COMPLETED": + installedDevices.add(deviceDetail); + statusCounts.put("COMPLETED", statusCounts.get("COMPLETED") + 1); + break; + case "ERROR": + case "INVALID": + case "UNAUTHORIZED": + errorDevices.add(deviceDetail); + statusCounts.put("ERROR", statusCounts.get("ERROR") + 1); + break; + case "IN_PROGRESS": + case "PENDING": + case "REPEATED": + pendingDevices.add(deviceDetail); + statusCounts.put("PENDING", statusCounts.get("PENDING") + 1); + break; + } + } else { + DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); + newDeviceDetail.setDeviceId(deviceId); + newDeviceDetail.setDeviceName(ownerWithDevice.getDeviceNames()); + newDeviceDetail.setDeviceOwner(ownerWithDevice.getUserName()); + newDeviceDetail.setDeviceStatus(ownerWithDevice.getDeviceStatus()); + newDeviceDetail.setType(ownerWithDevice.getDeviceTypes()); + newDeviceDetail.setDeviceIdentifier(ownerWithDevice.getDeviceIdentifiers()); + newDevices.add(newDeviceDetail); + statusCounts.put("NEW", statusCounts.get("NEW") + 1); + } + } + + int totalDevices = allDevices.size(); + Map statusPercentages = new HashMap<>(); + for (Map.Entry entry : statusCounts.entrySet()) { + double percentage = ((double) entry.getValue() / totalDevices) * 100; + String formattedPercentage = String.format("%.2f", percentage); + statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); + } + + CategorizedSubscriptionResult categorizedSubscriptionResult = + new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); + DeviceSubscriptionResponseDTO result = + new DeviceSubscriptionResponseDTO(totalDevices, statusPercentages, categorizedSubscriptionResult); + + return result; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while getting user subscriptions for the application release UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "DB Connection error occurred while getting user subscriptions for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DeviceManagementDAOException e) { + throw new RuntimeException(e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public List getSubscriptionOperationsByUUIDAndDeviceID(int deviceId, String uuid, int offset, int limit) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + if (uuid == null || uuid.isEmpty()) { + throw new IllegalArgumentException("UUID cannot be null or empty."); + } + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = this.applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); + List deviceSubscriptions = + subscriptionDAO.getSubscriptionOperationsByAppReleaseIDAndDeviceID(appReleaseId, deviceId, tenantId, offset, limit); + for (DeviceOperationDTO deviceSubscription : deviceSubscriptions) { + Integer operationId = deviceSubscription.getOperationId(); + if (operationId != null) { + OperationDTO operationDetails = deviceManagementProviderService.getOperationDetailsById(operationId); + if (operationDetails != null) { + deviceSubscription.setOperationCode(operationDetails.getOperationCode()); + deviceSubscription.setOperationDetails(operationDetails.getOperationDetails()); + deviceSubscription.setOperationProperties(operationDetails.getOperationProperties()); + deviceSubscription.setOperationResponses(operationDetails.getOperationResponses()); + } + } + } + return deviceSubscriptions; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while retrieving device subscriptions for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while retrieving the database connection"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (OperationManagementException e) { + throw new RuntimeException(e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public List getSubscriptionCountsByUUID(String uuid) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + if (uuid == null || uuid.isEmpty()) { + throw new IllegalArgumentException("UUID cannot be null or empty."); + } + + try { + ConnectionManagerUtil.openDBConnection(); + + ApplicationReleaseDTO applicationReleaseDTO = this.applicationReleaseDAO.getReleaseByUUID(uuid, tenantId); + if (applicationReleaseDTO == null) { + String msg = "Couldn't find an application release for application release UUID: " + uuid; + log.error(msg); + throw new NotFoundException(msg); + } + int appReleaseId = applicationReleaseDTO.getId(); + + List subscriptionCounts = new ArrayList<>(); + + subscriptionCounts.add(new CategorizedSubscriptionCountsDTO( + "All", + subscriptionDAO.getAllSubscriptionCount(appReleaseId, tenantId), + subscriptionDAO.getAllUnsubscriptionCount(appReleaseId, tenantId))); + subscriptionCounts.add(new CategorizedSubscriptionCountsDTO( + "Device", + subscriptionDAO.getDeviceSubscriptionCount(appReleaseId, tenantId), + subscriptionDAO.getDeviceUnsubscriptionCount(appReleaseId, tenantId))); + subscriptionCounts.add(new CategorizedSubscriptionCountsDTO( + "Group", + subscriptionDAO.getGroupSubscriptionCount(appReleaseId, tenantId), + subscriptionDAO.getGroupUnsubscriptionCount(appReleaseId, tenantId))); + subscriptionCounts.add(new CategorizedSubscriptionCountsDTO( + "Role", + subscriptionDAO.getRoleSubscriptionCount(appReleaseId, tenantId), + subscriptionDAO.getRoleUnsubscriptionCount(appReleaseId, tenantId))); + subscriptionCounts.add(new CategorizedSubscriptionCountsDTO( + "User", + subscriptionDAO.getUserSubscriptionCount(appReleaseId, tenantId), + subscriptionDAO.getUserUnsubscriptionCount(appReleaseId, tenantId))); + + return subscriptionCounts; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while retrieving subscriptions counts for UUID: " + uuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while retrieving the database connection"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } } diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/DAOUtil.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/DAOUtil.java index 2177c6ad13..6b06a7aa62 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/DAOUtil.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/DAOUtil.java @@ -383,7 +383,6 @@ public class DAOUtil { activity.setAppType(rs.getString("TYPE")); activity.setUsername(rs.getString("SUBSCRIBED_BY")); activity.setPackageName(rs.getString("PACKAGE_NAME")); - activity.setStatus(rs.getString("STATUS")); activity.setVersion(rs.getString("VERSION")); activity.setTriggeredBy(rs.getString("ACTION_TRIGGERED_FROM")); activities.add(activity); diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/test/java/io/entgra/device/mgt/core/application/mgt/core/BaseTestCase.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/test/java/io/entgra/device/mgt/core/application/mgt/core/BaseTestCase.java index 2984525a4f..fd11a7f292 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/test/java/io/entgra/device/mgt/core/application/mgt/core/BaseTestCase.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/test/java/io/entgra/device/mgt/core/application/mgt/core/BaseTestCase.java @@ -30,6 +30,7 @@ import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManag import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tomcat.jdbc.pool.PoolProperties; @@ -96,6 +97,7 @@ public abstract class BaseTestCase { ConnectionManagerUtil.init(dataSource); DeviceManagementDAOFactory.init(dataSource); MetadataManagementDAOFactory.init(dataSource); + OperationManagementDAOFactory.init(dataSource); // PolicyManagementDAOFactory.init(dataSource); // OperationManagementDAOFactory.init(dataSource); // GroupManagementDAOFactory.init(dataSource); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/ActivityProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/ActivityProviderServiceImpl.java index 41d56dbe54..5e5ba9d033 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/ActivityProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/ActivityProviderServiceImpl.java @@ -168,7 +168,6 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService activity.setUsername(appActivity.getUsername()); activity.setPackageName(appActivity.getPackageName()); activity.setAppName(appActivity.getAppName()); - activity.setStatus(appActivity.getStatus()); activity.setAppType(appActivity.getAppType()); activity.setVersion(appActivity.getVersion()); activity.setTriggeredBy(appActivity.getTriggeredBy()); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/MDMAppConstants.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/MDMAppConstants.java index da042f8d93..60d9503c97 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/MDMAppConstants.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/MDMAppConstants.java @@ -58,6 +58,8 @@ public class MDMAppConstants { } public static final String INSTALL_ENTERPRISE_APPLICATION = "INSTALL_ENTERPRISE_APPLICATION"; public static final String UNINSTALL_ENTERPRISE_APPLICATION = "UNINSTALL_ENTERPRISE_APPLICATION"; + public static final String INSTALL_WEB_CLIP_APPLICATION = "INSTALL_WEB_CLIP"; + public static final String UNINSTALL_WEB_CLIP_APPLICATION = "UNINSTALL_WEB_CLIP"; //App type constants related to window device type public static final String MSI = "MSI"; public static final String APPX = "APPX"; diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/app/mgt/windows/WebClipApplication.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/app/mgt/windows/WebClipApplication.java new file mode 100644 index 0000000000..be4feae54e --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/app/mgt/windows/WebClipApplication.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.device.mgt.common.app.mgt.windows; +import com.google.gson.Gson; + +import java.util.Properties; + +public class WebClipApplication { + + private String url; + private String name; + private String icon; + private String type; + private Properties properties; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } + + public String toJSON() { + Gson gson = new Gson(); + return gson.toJson(this); + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/EnrollmentDAO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/EnrollmentDAO.java index 302c5ff721..5432cac6fb 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/EnrollmentDAO.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/EnrollmentDAO.java @@ -21,8 +21,11 @@ import io.entgra.device.mgt.core.device.mgt.common.Device; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo; import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo.Status; +import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; import java.util.List; +import java.util.Map; public interface EnrollmentDAO { @@ -93,5 +96,33 @@ public interface EnrollmentDAO { */ boolean addDeviceStatus(int enrolmentId, EnrolmentInfo.Status status) throws DeviceManagementDAOException; + /** + * Retrieves owners and the list of device IDs related to an owner. + * + * @param owner the owner whose device IDs need to be retrieved + * @param tenantId the ID of the tenant + * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user + * @throws DeviceManagementDAOException if an error occurs while fetching the data + */ + OwnerWithDeviceDTO getOwnersWithDevices(String owner, int tenantId) throws DeviceManagementDAOException; + + /** + * Retrieves a list of device IDs with owners and device status. + * + * @param deviceId the deviceId of the device which user need to be retrieved + * @param tenantId the ID of the tenant + * @return {@link OwnerWithDeviceDTO} which contains a list of devices + * @throws DeviceManagementDAOException if an error occurs while fetching the data + */ + OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, int tenantId) + throws DeviceManagementDAOException; + /** + * Retrieves owners and the list of device IDs with device status. + * + * @param tenantId the ID of the tenant + * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user + * @throws DeviceManagementDAOException if an error occurs while fetching the data + */ + List getDevicesByTenantId(int tenantId) throws DeviceManagementDAOException; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GroupDAO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GroupDAO.java index e9802900f9..5071f7a400 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GroupDAO.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GroupDAO.java @@ -23,6 +23,7 @@ import io.entgra.device.mgt.core.device.mgt.common.GroupPaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupRoleWrapper; +import io.entgra.device.mgt.core.device.mgt.core.dto.GroupDetailsDTO; import java.util.List; import java.util.Map; @@ -468,4 +469,17 @@ public interface GroupDAO { List groupNames) throws GroupManagementDAOException; + /** + * Get group details and list of device IDs related to the group. + * + * @param groupName Group name + * @param tenantId Tenant ID + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link GroupDetailsDTO} which containing group details and a list of device IDs + * @throws GroupManagementDAOException if an error occurs while retrieving the group details and devices + */ + GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int tenantId, int offset, int limit) + throws GroupManagementDAOException; + } \ No newline at end of file diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java index f4e990d577..25201ddc79 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java @@ -17,23 +17,32 @@ */ package io.entgra.device.mgt.core.device.mgt.core.dao.impl; -import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.context.PrivilegedCarbonContext; import io.entgra.device.mgt.core.device.mgt.common.Device; +import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.DeviceManagementConstants; import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.dao.EnrollmentDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; -import java.sql.*; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.List; public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO { + private static final Log log = LogFactory.getLog(AbstractEnrollmentDAOImpl.class); @Override public EnrolmentInfo addEnrollment(int deviceId, DeviceIdentifier deviceIdentifier, EnrolmentInfo enrolmentInfo, @@ -553,4 +562,117 @@ public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO { return enrolmentInfo; } + @Override + public OwnerWithDeviceDTO getOwnersWithDevices(String owner, int tenantId) + throws DeviceManagementDAOException { + Connection conn = null; + OwnerWithDeviceDTO ownerDetails = new OwnerWithDeviceDTO(); + List deviceIds = new ArrayList<>(); + int deviceCount = 0; + + String sql = "SELECT e.DEVICE_ID, e.OWNER, e.STATUS AS DEVICE_STATUS, d.NAME AS DEVICE_NAME, e.DEVICE_TYPE AS DEVICE_TYPE, e.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION " + + "FROM DM_ENROLMENT e " + + "JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " + + "WHERE e.OWNER = ? AND e.TENANT_ID = ?"; + try { + conn = this.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, owner); + stmt.setInt(2, tenantId); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + if (ownerDetails.getUserName() == null) { + ownerDetails.setUserName(rs.getString("OWNER")); + } + deviceIds.add(rs.getInt("DEVICE_ID")); + deviceCount++; + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving owners and device IDs for owner: " + owner; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + + ownerDetails.setDeviceIds(deviceIds); + ownerDetails.setDeviceStatus("DEVICE_STATUS"); + ownerDetails.setDeviceNames("DEVICE_NAME"); + ownerDetails.setDeviceTypes("DEVICE_TYPE"); + ownerDetails.setDeviceIdentifiers("DEVICE_IDENTIFICATION"); + ownerDetails.setDeviceCount(deviceCount); + return ownerDetails; + } + + @Override + public OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, int tenantId) + throws DeviceManagementDAOException { + OwnerWithDeviceDTO deviceOwnerWithStatus = new OwnerWithDeviceDTO(); + Connection conn = null; + String sql = "SELECT e.DEVICE_ID, e.OWNER, e.STATUS AS DEVICE_STATUS, d.NAME AS DEVICE_NAME, e.DEVICE_TYPE, e.DEVICE_IDENTIFICATION " + + "FROM DM_ENROLMENT e " + + "JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " + + "WHERE e.DEVICE_ID = ? AND e.TENANT_ID = ?"; + try { + conn = this.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + deviceOwnerWithStatus.setUserName(rs.getString("OWNER")); + deviceOwnerWithStatus.setDeviceStatus(rs.getString("DEVICE_STATUS")); + List deviceIds = new ArrayList<>(); + deviceIds.add(rs.getInt("DEVICE_ID")); + deviceOwnerWithStatus.setDeviceIds(deviceIds); + deviceOwnerWithStatus.setDeviceNames(rs.getString("DEVICE_NAME")); + deviceOwnerWithStatus.setDeviceTypes(rs.getString("DEVICE_TYPE")); + deviceOwnerWithStatus.setDeviceIdentifiers(rs.getString("DEVICE_IDENTIFICATION")); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving owner and status for device ID: " + deviceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + return deviceOwnerWithStatus; + } + + @Override + public List getDevicesByTenantId(int tenantId) + throws DeviceManagementDAOException { + List devices = new ArrayList<>(); + String sql = "SELECT DEVICE_ID, OWNER, STATUS, DEVICE_TYPE, DEVICE_IDENTIFICATION " + + "FROM DM_ENROLMENT " + + "WHERE TENANT_ID = ?"; + Connection conn = null; + + try { + conn = this.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + DeviceDetailsDTO device = new DeviceDetailsDTO(); + device.setDeviceId(rs.getInt("DEVICE_ID")); + device.setOwner(rs.getString("OWNER")); + device.setStatus(rs.getString("STATUS")); + device.setType(rs.getString("DEVICE_TYPE")); + device.setDeviceIdentifier(rs.getString("DEVICE_IDENTIFICATION")); + devices.add(device); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving devices for tenant ID: " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + return devices; + } + } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java index 2cb472d1ff..9232178b36 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java @@ -24,6 +24,7 @@ import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupRoleWrapper; import io.entgra.device.mgt.core.device.mgt.core.dao.GroupDAO; +import io.entgra.device.mgt.core.device.mgt.core.dto.GroupDetailsDTO; import io.entgra.device.mgt.core.device.mgt.core.dao.GroupManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dao.GroupManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.dao.util.DeviceManagementDAOUtil; @@ -164,7 +165,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } catch (SQLException e) { String msg = "Error occurred while retrieving groups of groups IDs " + deviceGroupIds.toString() - + " in tenant: " + tenantId; + + " in tenant: " + tenantId; log.error(msg); throw new GroupManagementDAOException(msg, e); } @@ -184,7 +185,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { for (int i = 0; i < deviceGroupIdsCount; i++) { sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; } - sql += ")"; + sql += ")"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { int paramIndex = 1; stmt.setInt(paramIndex++, tenantId); @@ -202,7 +203,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } catch (SQLException e) { String msg = "Error occurred while retrieving groups of groups IDs " + deviceGroupIds - + " in tenant: " + tenantId; + + " in tenant: " + tenantId; log.error(msg); throw new GroupManagementDAOException(msg, e); } @@ -227,7 +228,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { sql += " AND OWNER LIKE ?"; } if (StringUtils.isNotBlank(request.getParentPath())) { - if(isWithParentPath){ + if (isWithParentPath) { sql += " AND PARENT_PATH LIKE ?"; } } @@ -250,7 +251,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(paramIndex++, request.getOwner() + "%"); } if (StringUtils.isNotBlank(request.getParentPath())) { - if(isWithParentPath){ + if (isWithParentPath) { stmt.setString(paramIndex++, request.getParentPath()); } } @@ -271,7 +272,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } catch (SQLException e) { String msg = "Error occurred while retrieving groups of groups IDs " + deviceGroupIds.toString() - + " in tenant: " + tenantId; + + " in tenant: " + tenantId; log.error(msg); throw new GroupManagementDAOException(msg, e); } @@ -484,7 +485,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, STATUS = ?, " + "PARENT_PATH = ?, PARENT_GROUP_ID = ? WHERE ID = ? AND TENANT_ID = ?"; - try (PreparedStatement stmt = conn.prepareStatement(sql)){ + try (PreparedStatement stmt = conn.prepareStatement(sql)) { for (DeviceGroup deviceGroup : deviceGroups) { stmt.setString(1, deviceGroup.getDescription()); stmt.setString(2, deviceGroup.getName()); @@ -609,6 +610,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { throw new GroupManagementDAOException(msg, e); } } + @Override public void deleteGroups(List groupIds, int tenantId) throws GroupManagementDAOException { try { @@ -1166,7 +1168,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { if (StringUtils.isNotBlank(parentPath)) { sql += " AND g.PARENT_PATH = ? "; } - sql += "GROUP BY g.ID"; + sql += "GROUP BY g.ID"; stmt = conn.prepareStatement(sql); int index = 0; while (index++ < rolesCount) { @@ -1279,7 +1281,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { return devices; } Connection conn = GroupManagementDAOFactory.getConnection(); - StringJoiner joiner = new StringJoiner(",","SELECT " + StringJoiner joiner = new StringJoiner(",", "SELECT " + "d1.DEVICE_ID, " + "d1.DESCRIPTION, " + "d1.NAME AS DEVICE_NAME, " @@ -1437,4 +1439,80 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } return groupUnassignedDeviceList; } + + @Override + public GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int tenantId, int offset, int limit) + throws GroupManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get group details and device IDs for group: " + groupName); + } + GroupDetailsDTO groupDetails = new GroupDetailsDTO(); + List deviceIds = new ArrayList<>(); + Map deviceOwners = new HashMap<>(); + Map deviceStatuses = new HashMap<>(); + Map deviceNames = new HashMap<>(); + Map deviceTypes = new HashMap<>(); + Map deviceIdentifiers = new HashMap<>(); + + String sql = + "SELECT " + + " g.ID AS GROUP_ID, " + + " g.GROUP_NAME, " + + " g.OWNER AS GROUP_OWNER, " + + " e.OWNER AS DEVICE_OWNER, " + + " e.STATUS AS DEVICE_STATUS, " + + " e.DEVICE_TYPE AS DEVICE_TYPE, " + + " e.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + " dgm.DEVICE_ID, " + + " d.NAME AS DEVICE_NAME " + + "FROM " + + " DM_GROUP g " + + " JOIN DM_DEVICE_GROUP_MAP dgm ON g.ID = dgm.GROUP_ID " + + " JOIN DM_ENROLMENT e ON dgm.DEVICE_ID = e.DEVICE_ID " + + " JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " + + "WHERE " + + " g.GROUP_NAME = ? " + + " AND g.TENANT_ID = ? " + + "LIMIT ? OFFSET ?"; + + Connection conn = null; + try { + conn = GroupManagementDAOFactory.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, groupName); + stmt.setInt(2, tenantId); + stmt.setInt(3, limit); + stmt.setInt(4, offset); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + if (groupDetails.getGroupId() == 0) { + groupDetails.setGroupId(rs.getInt("GROUP_ID")); + groupDetails.setGroupName(rs.getString("GROUP_NAME")); + groupDetails.setGroupOwner(rs.getString("GROUP_OWNER")); + } + int deviceId = rs.getInt("DEVICE_ID"); + deviceIds.add(deviceId); + deviceOwners.put(deviceId, rs.getString("DEVICE_OWNER")); + deviceStatuses.put(deviceId, rs.getString("DEVICE_STATUS")); + deviceNames.put(deviceId, rs.getString("DEVICE_NAME")); + deviceTypes.put(deviceId, rs.getString("DEVICE_TYPE")); + deviceIdentifiers.put(deviceId, rs.getString("DEVICE_IDENTIFICATION")); + } + } + groupDetails.setDeviceIds(deviceIds); + groupDetails.setDeviceCount(deviceIds.size()); + groupDetails.setDeviceOwners(deviceOwners); + groupDetails.setDeviceStatuses(deviceStatuses); + groupDetails.setDeviceNames(deviceNames); + groupDetails.setDeviceTypes(deviceTypes); + groupDetails.setDeviceIdentifiers(deviceIdentifiers); + return groupDetails; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving group details and device IDs for group: " + groupName; + log.error(msg, e); + throw new GroupManagementDAOException(msg, e); + } + } } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/DeviceDetailsDTO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/DeviceDetailsDTO.java new file mode 100644 index 0000000000..bb25d55c52 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/DeviceDetailsDTO.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.device.mgt.core.dto; + +public class DeviceDetailsDTO { + private int deviceId; + private String owner; + private String status; + private String type; + private String deviceIdentifier; + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDeviceIdentifier() { + return deviceIdentifier; + } + + public void setDeviceIdentifier(String deviceIdentifier) { + this.deviceIdentifier = deviceIdentifier; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/GroupDetailsDTO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/GroupDetailsDTO.java new file mode 100644 index 0000000000..c3a20d5217 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/GroupDetailsDTO.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.device.mgt.core.dto; + +import java.util.List; +import java.util.Map; + +public class GroupDetailsDTO { + private int groupId; + private String groupName; + private String groupOwner; + private List deviceIds; + private int deviceCount; + private String deviceOwner; + private String deviceStatus; + private Map deviceOwners; + private Map deviceStatuses; + private Map deviceNames; + private Map deviceTypes; + private Map deviceIdentifiers; + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public String getGroupOwner() { + return groupOwner; + } + + public void setGroupOwner(String groupOwner) { + this.groupOwner = groupOwner; + } + + public List getDeviceIds() { + return deviceIds; + } + + public void setDeviceIds(List deviceIds) { + this.deviceIds = deviceIds; + } + + public int getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(int deviceCount) { + this.deviceCount = deviceCount; + } + + public String getDeviceOwner() { + return deviceOwner; + } + + public void setDeviceOwner(String deviceOwner) { + this.deviceOwner = deviceOwner; + } + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public Map getDeviceOwners() { + return deviceOwners; + } + + public void setDeviceOwners(Map deviceOwners) { + this.deviceOwners = deviceOwners; + } + + public Map getDeviceStatuses() { + return deviceStatuses; + } + + public void setDeviceStatuses(Map deviceStatuses) { + this.deviceStatuses = deviceStatuses; + } + + public Map getDeviceNames() { + return deviceNames; + } + + public void setDeviceNames(Map deviceNames) { + this.deviceNames = deviceNames; + } + + public Map getDeviceTypes() { + return deviceTypes; + } + + public void setDeviceTypes(Map deviceTypes) { + this.deviceTypes = deviceTypes; + } + + public Map getDeviceIdentifiers() { + return deviceIdentifiers; + } + + public void setDeviceIdentifiers(Map deviceIdentifiers) { + this.deviceIdentifiers = deviceIdentifiers; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OperationDTO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OperationDTO.java new file mode 100644 index 0000000000..05530e231b --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OperationDTO.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 - 2023, 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.device.mgt.core.device.mgt.core.dto; + +import org.json.JSONObject; +import java.util.List; + +public class OperationDTO { + private int operationId; + private String operationCode; + private JSONObject operationDetails; + private JSONObject operationProperties; + private List operationResponses; + + // Getters and Setters + + public int getOperationId() { + return operationId; + } + + public void setOperationId(int operationId) { + this.operationId = operationId; + } + + public String getOperationCode() { + return operationCode; + } + + public void setOperationCode(String operationCode) { + this.operationCode = operationCode; + } + + public JSONObject getOperationDetails() { + return operationDetails; + } + + public void setOperationDetails(JSONObject operationDetails) { + this.operationDetails = operationDetails; + } + + public JSONObject getOperationProperties() { + return operationProperties; + } + + public void setOperationProperties(JSONObject operationProperties) { + this.operationProperties = operationProperties; + } + + public List getOperationResponses() { + return operationResponses; + } + + public void setOperationResponses(List operationResponses) { + this.operationResponses = operationResponses; + } +} diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/UserSubscriptionDTO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OperationResponseDTO.java similarity index 55% rename from components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/UserSubscriptionDTO.java rename to components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OperationResponseDTO.java index 4df7e4e64d..b52404ca0e 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.common/src/main/java/io/entgra/device/mgt/core/application/mgt/common/dto/UserSubscriptionDTO.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OperationResponseDTO.java @@ -16,17 +16,28 @@ * under the License. */ -package io.entgra.device.mgt.core.application.mgt.common.dto; +package io.entgra.device.mgt.core.device.mgt.core.dto; import java.sql.Timestamp; -public class UserSubscriptionDTO { - private int id; - private String subscribedBy; - private Timestamp subscribedTimestamp; - private boolean isUnsubscribed; - private String unsubscribedBy; - private Timestamp unsubscribedTimestamp; - private String subscribedFrom; - private String userName; +public class OperationResponseDTO { + private String operationResponse; + private Timestamp responseTimeStamp; + + public String getOperationResponse() { + return operationResponse; + } + + public void setOperationResponse(String operationResponse) { + this.operationResponse = operationResponse; + } + + public Timestamp getResponseTimeStamp() { + return responseTimeStamp; + } + + public void setResponseTimeStamp(Timestamp responseTimeStamp) { + this.responseTimeStamp = responseTimeStamp; + } } + diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OwnerWithDeviceDTO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OwnerWithDeviceDTO.java new file mode 100644 index 0000000000..be6f63702a --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dto/OwnerWithDeviceDTO.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018 - 2024, 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.device.mgt.core.device.mgt.core.dto; + +import java.util.List; + +public class OwnerWithDeviceDTO { + + private String userName; + private List deviceIds; + private int deviceCount; + private String deviceStatus; + private String deviceNames; + private String deviceTypes; + private String deviceIdentifiers; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public List getDeviceIds() { + return deviceIds; + } + + public void setDeviceIds(List deviceIds) { + this.deviceIds = deviceIds; + } + + public int getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(int deviceCount) { + this.deviceCount = deviceCount; + } + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDeviceNames() { + return deviceNames; + } + + public void setDeviceNames(String deviceNames) { + this.deviceNames = deviceNames; + } + + public String getDeviceTypes() { + return deviceTypes; + } + + public void setDeviceTypes(String deviceTypes) { + this.deviceTypes = deviceTypes; + } + + public String getDeviceIdentifiers() { + return deviceIdentifiers; + } + + public void setDeviceIdentifiers(String deviceIdentifiers) { + this.deviceIdentifiers = deviceIdentifiers; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java index 4abaf40022..c874283a76 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -23,6 +23,8 @@ import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationResponse; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; +import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationDTO; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.OperationResponseMeta; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMapping; @@ -124,4 +126,15 @@ public interface OperationDAO { int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) throws OperationManagementDAOException; + + /** + * This method is used to get the details of device subscriptions related to a UUID. + * + * @param operationId the operationId of the operation to be retrieved. + * @param tenantId id of the current tenant. + * @return {@link OperationDTO} which contains the details of device operations. + * @throws OperationManagementDAOException if connection establishment or SQL execution fails. + */ + OperationDTO getOperationDetailsById(int operationId, int tenantId) + throws OperationManagementDAOException; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index 8322905a5e..50ec3f1071 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -17,32 +17,36 @@ */ package io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.impl; -import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.ProfileOperation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.context.PrivilegedCarbonContext; import io.entgra.device.mgt.core.device.mgt.common.ActivityPaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; -import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityHolder; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityStatus; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationResponse; import io.entgra.device.mgt.core.device.mgt.core.DeviceManagementConstants; import io.entgra.device.mgt.core.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationResponseDTO; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.OperationResponseMeta; +import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.ProfileOperation; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMapping; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationDAO; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.util.OperationDAOUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONObject; +import org.wso2.carbon.context.PrivilegedCarbonContext; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; +import java.sql.Blob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -2774,4 +2778,66 @@ public class GenericOperationDAOImpl implements OperationDAO { } return 0; } + + @Override + public OperationDTO getOperationDetailsById(int operationId, int tenantId) + throws OperationManagementDAOException { + OperationDTO operationDetails = new OperationDTO(); + + String sql = "SELECT o.ID, " + + "o.OPERATION_CODE, " + + "o.OPERATION_DETAILS, " + + "o.OPERATION_PROPERTIES, " + + "r.OPERATION_RESPONSE, " + + "r.RECEIVED_TIMESTAMP " + + "FROM DM_OPERATION o " + + "LEFT JOIN DM_DEVICE_OPERATION_RESPONSE r " + + "ON o.ID = r.OPERATION_ID " + + "WHERE o.ID = ? " + + "AND o.TENANT_ID = ?"; + + try { + Connection conn = OperationManagementDAOFactory.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, operationId); + stmt.setInt(2, tenantId); + + try (ResultSet rs = stmt.executeQuery()) { + List responses = new ArrayList<>(); + while (rs.next()) { + if (operationDetails.getOperationId() == 0) { + operationDetails.setOperationId(rs.getInt("ID")); + operationDetails.setOperationCode(rs.getString("OPERATION_CODE")); + Blob detailsBlob = rs.getBlob("OPERATION_DETAILS"); + if (detailsBlob != null) { + JSONObject operationDetailsJson = OperationDAOUtil.convertBlobToJsonObject(detailsBlob); + operationDetails.setOperationDetails(operationDetailsJson); + } + Blob propertiesBlob = rs.getBlob("OPERATION_PROPERTIES"); + if (propertiesBlob != null) { + JSONObject operationPropertiesJson = OperationDAOUtil.convertBlobToJsonObject(propertiesBlob); + operationDetails.setOperationProperties(operationPropertiesJson); + } + } + + String response = rs.getString("OPERATION_RESPONSE"); + Timestamp responseTimestamp = rs.getTimestamp("RECEIVED_TIMESTAMP"); + if (response != null && responseTimestamp != null) { + OperationResponseDTO operationResponse = new OperationResponseDTO(); + operationResponse.setOperationResponse(response); + operationResponse.setResponseTimeStamp(responseTimestamp); + responses.add(operationResponse); + } + } + operationDetails.setOperationResponses(responses); + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving operation details for operation ID: " + operationId; + log.error(msg, e); + throw new OperationManagementDAOException(msg, e); + } + + return operationDetails; + } } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java index 4161d7b4c2..4e20be0ae2 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java @@ -24,17 +24,20 @@ import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityHolder; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityMapper; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityStatus; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationResponse; -import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.*; import io.entgra.device.mgt.core.device.mgt.core.DeviceManagementConstants; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.*; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.json.JSONObject; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.ObjectInputStream; +import java.sql.Blob; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; @@ -385,4 +388,53 @@ public class OperationDAOUtil { return operation; } + /** + * @param blob + * @return + * @throws SQLException + */ + public static JSONObject convertBlobToJsonObject(Blob blob) throws SQLException { + String jsonString; + try (InputStream inputStream = blob.getBinaryStream(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + int bytesRead; + byte[] buffer = new byte[4096]; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + byte[] blobBytes = outputStream.toByteArray(); + + // Check if the blob data is a serialized Java object + if (blobBytes.length > 2 && (blobBytes[0] & 0xFF) == 0xAC && (blobBytes[1] & 0xFF) == 0xED) { + // Deserialize the object + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(blobBytes))) { + Object obj = ois.readObject(); + if (obj instanceof String) { + jsonString = (String) obj; + } else { + jsonString = new JSONObject(obj).toString(); + } + } catch (ClassNotFoundException e) { + String msg = "Failed to deserialize object from BLOB"; + log.error(msg, e); + throw new SQLException(msg, e); + } + } else { + // If not serialized, treat it as plain JSON string + jsonString = new String(blobBytes, "UTF-8"); + } + } catch (IOException e) { + String msg = "Failed to convert BLOB to JSON string"; + log.error(msg, e); + throw new SQLException(msg, e); + } + // Convert JSON string to JSONObject + if (jsonString == null || jsonString.isEmpty()) { + String msg = "Converted JSON string is null or empty"; + log.error(msg); + throw new SQLException(msg); + } + return new JSONObject(jsonString); + } + } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java index 63c5832457..64b1c316ce 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java @@ -19,6 +19,9 @@ package io.entgra.device.mgt.core.device.mgt.core.service; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.Application; +import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; import org.apache.commons.collections.map.SingletonMap; import io.entgra.device.mgt.core.device.mgt.common.*; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.ApplicationManagementException; @@ -1065,4 +1068,39 @@ public interface DeviceManagementProviderService { List getEnrolledDevicesSince(Date since) throws DeviceManagementException; List getEnrolledDevicesPriorTo(Date before) throws DeviceManagementException; void deleteDeviceDataByTenantDomain(String tenantDomain) throws DeviceManagementException; + + /** + * Get owner details and device IDs for a given owner and tenant. + * + * @param owner the name of the owner. + * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user. + * @throws DeviceManagementException if an error occurs while fetching owner details. + */ + OwnerWithDeviceDTO getOwnersWithDeviceIds(String owner) throws DeviceManagementDAOException; + + /** + * Get owner details and device IDs for a given owner and tenant. + * + * @param deviceId the deviceId of the device. + * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user. + * @throws DeviceManagementException if an error occurs while fetching owner details. + */ + OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId) throws DeviceManagementDAOException; + + /** + * Get owner details and device IDs for a given owner and tenant. + * @param tenantId the tenant id which devices need to be retried + * @return {@link DeviceDetailsDTO} which contains devices details. + * @throws DeviceManagementException if an error occurs while fetching owner details. + */ + List getDevicesByTenantId(int tenantId) throws DeviceManagementDAOException; + + /** + * Get operation details by operation code. + * + * @param operationId the id of the operation. + * @return {@link OperationDTO} which contains operation details. + * @throws OperationManagementException if an error occurs while fetching the operation details. + */ + OperationDTO getOperationDetailsById(int operationId) throws OperationManagementException; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 910ef25a8b..0d0e03285e 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -22,6 +22,11 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.core.dao.TenantDAO; +import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; +import io.entgra.device.mgt.core.device.mgt.core.dto.OperationDTO; +import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; +import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.extensions.logger.spi.EntgraLogger; import io.entgra.device.mgt.core.notification.logger.DeviceEnrolmentLogContext; import io.entgra.device.mgt.core.notification.logger.impl.EntgraDeviceEnrolmentLoggerImpl; @@ -120,6 +125,7 @@ import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceStatusDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceTypeDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.EnrollmentDAO; +import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.util.DeviceManagementDAOUtil; import io.entgra.device.mgt.core.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; import io.entgra.device.mgt.core.device.mgt.core.device.details.mgt.DeviceInformationManager; @@ -173,6 +179,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv private final DeviceDAO deviceDAO; private final DeviceTypeDAO deviceTypeDAO; private final EnrollmentDAO enrollmentDAO; + private final OperationDAO operationDAO; private final ApplicationDAO applicationDAO; private MetadataDAO metadataDAO; private final DeviceStatusDAO deviceStatusDAO; @@ -185,6 +192,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv this.applicationDAO = DeviceManagementDAOFactory.getApplicationDAO(); this.deviceTypeDAO = DeviceManagementDAOFactory.getDeviceTypeDAO(); this.enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + this.operationDAO = OperationManagementDAOFactory.getOperationDAO(); this.metadataDAO = MetadataManagementDAOFactory.getMetadataDAO(); this.deviceStatusDAO = DeviceManagementDAOFactory.getDeviceStatusDAO(); this.tenantDao = DeviceManagementDAOFactory.getTenantDAO(); @@ -5347,4 +5355,106 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv DeviceManagementDAOFactory.closeConnection(); } } + + @Override + public OwnerWithDeviceDTO getOwnersWithDeviceIds(String owner) throws DeviceManagementDAOException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + OwnerWithDeviceDTO ownerWithDeviceDTO; + + try { + DeviceManagementDAOFactory.openConnection(); + ownerWithDeviceDTO = this.enrollmentDAO.getOwnersWithDevices(owner, tenantId); + if (ownerWithDeviceDTO == null) { + String msg = "No data found for owner: " + owner; + log.error(msg); + throw new DeviceManagementDAOException(msg); + } + List deviceIds = ownerWithDeviceDTO.getDeviceIds(); + if (deviceIds != null) { + ownerWithDeviceDTO.setDeviceCount(deviceIds.size()); + } else { + ownerWithDeviceDTO.setDeviceCount(0); + } + } catch (DeviceManagementDAOException | SQLException e) { + String msg = "Error occurred while retrieving device IDs for owner: " + owner; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + return ownerWithDeviceDTO; + } + + + @Override + public OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId) throws DeviceManagementDAOException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + OwnerWithDeviceDTO deviceOwnerWithStatus; + + try { + DeviceManagementDAOFactory.openConnection(); + deviceOwnerWithStatus = enrollmentDAO.getOwnerWithDeviceByDeviceId(deviceId, tenantId); + if (deviceOwnerWithStatus == null) { + throw new DeviceManagementDAOException("No data found for device ID: " + deviceId); + } + List deviceIds = deviceOwnerWithStatus.getDeviceIds(); + if (deviceIds != null) { + deviceOwnerWithStatus.setDeviceCount(deviceIds.size()); + } else { + deviceOwnerWithStatus.setDeviceCount(0); + } + } catch (DeviceManagementDAOException | SQLException e) { + String msg = "Error occurred while retrieving owner and status for device ID: " + deviceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + return deviceOwnerWithStatus; + } + + @Override + public List getDevicesByTenantId(int tenantId) throws DeviceManagementDAOException { + List devices; + try { + DeviceManagementDAOFactory.openConnection(); + devices = enrollmentDAO.getDevicesByTenantId(tenantId); + if (devices == null || devices.isEmpty()) { + String msg = "No devices found for tenant ID: " + tenantId; + log.error(msg); + throw new DeviceManagementDAOException(msg); + } + } catch (DeviceManagementDAOException | SQLException e) { + String msg = "Error occurred while retrieving devices for tenant ID: " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + return devices; + } + + + @Override + public OperationDTO getOperationDetailsById(int operationId) throws OperationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + OperationDTO operationDetails; + try { + OperationManagementDAOFactory.openConnection(); + operationDetails = this.operationDAO.getOperationDetailsById(operationId, tenantId); + if (operationDetails == null) { + String msg = "No operation details found for operation ID: " + operationId; + log.error(msg); + throw new OperationManagementException(msg); + } + } catch (SQLException | OperationManagementDAOException e) { + String msg = "Error occurred while retrieving operation details for operation ID: " + operationId; + log.error(msg, e); + throw new OperationManagementException(msg, e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + return operationDetails; + } + } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderService.java index d6040274ef..fac06bfccf 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderService.java @@ -20,10 +20,17 @@ package io.entgra.device.mgt.core.device.mgt.core.service; import io.entgra.device.mgt.core.device.mgt.common.Device; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceNotFoundException; import io.entgra.device.mgt.core.device.mgt.common.GroupPaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.PaginationResult; -import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceNotFoundException; -import io.entgra.device.mgt.core.device.mgt.common.group.mgt.*; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupRoleWrapper; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceTypesOfGroups; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupAlreadyExistException; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupNotExistException; +import io.entgra.device.mgt.core.device.mgt.common.group.mgt.RoleDoesNotExistException; +import io.entgra.device.mgt.core.device.mgt.core.dto.GroupDetailsDTO; import org.wso2.carbon.user.api.AuthorizationManager; import org.wso2.carbon.user.api.UserStoreManager; @@ -365,4 +372,16 @@ public interface GroupManagementProviderService { DeviceTypesOfGroups getDeviceTypesOfGroups(List identifiers) throws GroupManagementException; DeviceGroup getUserOwnGroup(int groupId, boolean requireGroupProps, int depth) throws GroupManagementException; + + /** + * Get group details and device IDs for a given group name. + * + * @param groupName the name of the group. + * @param offset the offset for the data set + * @param limit the limit for the data set + * @return {@link GroupDetailsDTO} which containing group details and a list of device IDs + * @throws GroupManagementException if an error occurs while fetching group details. + */ + GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int offset, int limit) throws GroupManagementException; + } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java index 27e8b6bba0..62b1ab8579 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -40,6 +40,7 @@ import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupAlreadyExistEx import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupManagementException; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.GroupNotExistException; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.RoleDoesNotExistException; +import io.entgra.device.mgt.core.device.mgt.core.dto.GroupDetailsDTO; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; @@ -1629,6 +1630,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid createGroupWithChildren(nextParentGroup, childrenGroups, requireGroupProps, tenantId, depth, counter); } } + @Override public DeviceTypesOfGroups getDeviceTypesOfGroups(List identifiers) throws GroupManagementException { DeviceTypesOfGroups deviceTypesOfGroups = new DeviceTypesOfGroups(); @@ -1685,4 +1687,37 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid return deviceTypesOfGroups; } + + @Override + public GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int offset, int limit) + throws GroupManagementException { + if (log.isDebugEnabled()) { + log.debug("Retrieving group details and device IDs for group: " + groupName); + } + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + GroupDetailsDTO groupDetailsWithDevices; + + try { + GroupManagementDAOFactory.openConnection(); + groupDetailsWithDevices = this.groupDAO.getGroupDetailsWithDevices(groupName, tenantId, offset, limit); + } catch (GroupManagementDAOException | SQLException e) { + String msg = "Error occurred while retrieving group details and device IDs for group: " + groupName; + log.error(msg, e); + throw new GroupManagementException(msg, e); + } finally { + GroupManagementDAOFactory.closeConnection(); + } + + if (groupDetailsWithDevices != null) { + List deviceIds = groupDetailsWithDevices.getDeviceIds(); + if (deviceIds != null) { + groupDetailsWithDevices.setDeviceCount(deviceIds.size()); + } else { + groupDetailsWithDevices.setDeviceCount(0); + } + } + + return groupDetailsWithDevices; + } + } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/status/task/impl/DeviceStatusMonitoringTask.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/status/task/impl/DeviceStatusMonitoringTask.java index fd9958782b..9ef7d0bb48 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/status/task/impl/DeviceStatusMonitoringTask.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/status/task/impl/DeviceStatusMonitoringTask.java @@ -37,10 +37,15 @@ import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.status.task.DeviceStatusTaskException; import io.entgra.device.mgt.core.device.mgt.core.task.impl.DynamicPartitionedScheduleTask; import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.service.RealmService; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * This implements the Task service which monitors the device activity periodically & update the device-status if @@ -92,33 +97,70 @@ public class DeviceStatusMonitoringTask extends DynamicPartitionedScheduleTask { try { List enrolmentInfoTobeUpdated = new ArrayList<>(); List allDevicesForMonitoring = getAllDevicesForMonitoring(); - long timeMillis = System.currentTimeMillis(); - for (DeviceMonitoringData monitoringData : allDevicesForMonitoring) { - long lastUpdatedTime = (timeMillis - monitoringData - .getLastUpdatedTime()) / 1000; - - EnrolmentInfo enrolmentInfo = monitoringData.getDevice().getEnrolmentInfo(); - EnrolmentInfo.Status status = null; - if (lastUpdatedTime >= deviceStatusTaskPluginConfig - .getIdleTimeToMarkInactive()) { - status = EnrolmentInfo.Status.INACTIVE; - } else if (lastUpdatedTime >= deviceStatusTaskPluginConfig - .getIdleTimeToMarkUnreachable()) { - status = EnrolmentInfo.Status.UNREACHABLE; + Map> tenantDevicesMap = new HashMap<>(); + List tenantMonitoringData = null; + //Delegate the devices in each tenant to a separate list to be updated the statuses. + //This improvement has been done since the tenants maintain a separate caches and the task is running + //in the super-tenant space. Hence, the device status updates are not reflected in the tenant caches. + //Refer to https://roadmap.entgra.net/issues/11386 for more information. + for (DeviceMonitoringData deviceMonitoringData : allDevicesForMonitoring) { + tenantMonitoringData = tenantDevicesMap.get(deviceMonitoringData.getTenantId()); + if (tenantMonitoringData == null) { + tenantMonitoringData = new ArrayList<>(); } + tenantMonitoringData.add(deviceMonitoringData); + tenantDevicesMap.put(deviceMonitoringData.getTenantId(), tenantMonitoringData); + } - if (status != null) { - enrolmentInfo.setStatus(status); - enrolmentInfoTobeUpdated.add(enrolmentInfo); - DeviceIdentifier deviceIdentifier = - new DeviceIdentifier(monitoringData.getDevice() - .getDeviceIdentifier(), deviceType); - monitoringData.getDevice().setEnrolmentInfo(enrolmentInfo); - DeviceCacheManagerImpl.getInstance().addDeviceToCache(deviceIdentifier, - monitoringData.getDevice(), monitoringData.getTenantId()); + List monitoringDevices = null; + long timeMillis = System.currentTimeMillis(); + //Retrieving the devices belongs for each tenants and updating the status of the devices. + for (Map.Entry> entry : tenantDevicesMap.entrySet()) { + Integer tenantId = entry.getKey(); + RealmService realmService = DeviceManagementDataHolder.getInstance().getRealmService(); + if (realmService != null) { + String domain = realmService.getTenantManager().getDomain(tenantId); + if (domain != null) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(domain, true); + monitoringDevices = entry.getValue(); + for (DeviceMonitoringData monitoringData : monitoringDevices) { + long lastUpdatedTime = (timeMillis - monitoringData + .getLastUpdatedTime()) / 1000; + + EnrolmentInfo enrolmentInfo = monitoringData.getDevice().getEnrolmentInfo(); + EnrolmentInfo.Status status = null; + if (lastUpdatedTime >= deviceStatusTaskPluginConfig + .getIdleTimeToMarkInactive()) { + status = EnrolmentInfo.Status.INACTIVE; + } else if (lastUpdatedTime >= deviceStatusTaskPluginConfig + .getIdleTimeToMarkUnreachable()) { + status = EnrolmentInfo.Status.UNREACHABLE; + } + + if (status != null) { + enrolmentInfo.setStatus(status); + enrolmentInfoTobeUpdated.add(enrolmentInfo); + DeviceIdentifier deviceIdentifier = + new DeviceIdentifier(monitoringData.getDevice() + .getDeviceIdentifier(), deviceType); + monitoringData.getDevice().setEnrolmentInfo(enrolmentInfo); + DeviceCacheManagerImpl.getInstance().addDeviceToCache(deviceIdentifier, + monitoringData.getDevice(), monitoringData.getTenantId()); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } else { + log.error("Failed while running the device status update task. Failed while " + + "extracting tenant domain of the tenant id : " + tenantId); + } + } else { + log.error("Failed while running the device status update task. RealmService is not initiated"); } } - if (!enrolmentInfoTobeUpdated.isEmpty()) { try { this.updateDeviceStatus(enrolmentInfoTobeUpdated); @@ -127,11 +169,12 @@ public class DeviceStatusMonitoringTask extends DynamicPartitionedScheduleTask { "device-status of devices of type '" + deviceType + "'", e); } } - - } catch (DeviceManagementException e) { String msg = "Error occurred while retrieving devices list for monitoring."; log.error(msg, e); + } catch (UserStoreException e) { + String msg = "Error occurred while retrieving RealmService instance for updating device status."; + log.error(msg, e); } } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/util/MDMWindowsOperationUtil.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/util/MDMWindowsOperationUtil.java index ac963c0a31..e06092cd97 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/util/MDMWindowsOperationUtil.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/util/MDMWindowsOperationUtil.java @@ -28,6 +28,7 @@ import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.windows.EnterpriseApplication; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.windows.HostedAppxApplication; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.windows.HostedMSIApplication; +import io.entgra.device.mgt.core.device.mgt.common.app.mgt.windows.WebClipApplication; import io.entgra.device.mgt.core.device.mgt.common.exceptions.UnknownApplicationTypeException; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.ProfileOperation; @@ -54,7 +55,6 @@ public class MDMWindowsOperationUtil { public static Operation createInstallAppOperation(App application) throws UnknownApplicationTypeException { ProfileOperation operation = new ProfileOperation(); - operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_ENTERPRISE_APPLICATION); operation.setType(Operation.Type.PROFILE); String appType = windowsAppType(application.getName()); String metaData = application.getMetaData(); @@ -62,6 +62,7 @@ public class MDMWindowsOperationUtil { switch (application.getType()) { case ENTERPRISE: + operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_ENTERPRISE_APPLICATION); EnterpriseApplication enterpriseApplication = new EnterpriseApplication(); if (appType.equalsIgnoreCase(MDMAppConstants.WindowsConstants.APPX)) { HostedAppxApplication hostedAppxApplication = new HostedAppxApplication(); @@ -111,6 +112,16 @@ public class MDMWindowsOperationUtil { } operation.setPayLoad(enterpriseApplication.toJSON()); break; + case WEB_CLIP: + operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_WEB_CLIP_APPLICATION); + WebClipApplication webClipApplication = new WebClipApplication(); + webClipApplication.setUrl(application.getLocation()); + webClipApplication.setName(application.getName()); + webClipApplication.setIcon(application.getIconImage()); + webClipApplication.setProperties(application.getProperties()); + webClipApplication.setType(application.getType().toString()); + operation.setPayLoad(webClipApplication.toJSON()); + break; default: String msg = "Application type " + application.getType() + " is not supported"; log.error(msg); @@ -130,7 +141,6 @@ public class MDMWindowsOperationUtil { public static Operation createUninstallAppOperation(App application) throws UnknownApplicationTypeException { ProfileOperation operation = new ProfileOperation(); - operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_ENTERPRISE_APPLICATION); operation.setType(Operation.Type.PROFILE); String appType = windowsAppType(application.getName()); String metaData = application.getMetaData(); @@ -138,6 +148,7 @@ public class MDMWindowsOperationUtil { switch (application.getType()) { case ENTERPRISE: + operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_ENTERPRISE_APPLICATION); EnterpriseApplication enterpriseApplication = new EnterpriseApplication(); if (appType.equalsIgnoreCase(MDMAppConstants.WindowsConstants.APPX)) { HostedAppxApplication hostedAppxApplication = new HostedAppxApplication(); @@ -187,6 +198,15 @@ public class MDMWindowsOperationUtil { } operation.setPayLoad(enterpriseApplication.toJSON()); break; + case WEB_CLIP: + operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_WEB_CLIP_APPLICATION); + WebClipApplication webClipApplication = new WebClipApplication(); + webClipApplication.setUrl(application.getLocation()); + webClipApplication.setName(application.getName()); + webClipApplication.setIcon(application.getIconImage()); + webClipApplication.setProperties(application.getProperties()); + webClipApplication.setType(application.getType().toString()); + operation.setPayLoad(webClipApplication.toJSON()); default: String msg = "Application type " + application.getType() + " is not supported"; log.error(msg); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java index 010262a341..bf0e69b0d2 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java @@ -20,13 +20,19 @@ package io.entgra.device.mgt.core.device.mgt.core.dao; import io.entgra.device.mgt.core.device.mgt.common.Device; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; +import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo; import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo.Status; +import io.entgra.device.mgt.core.device.mgt.common.device.details.DeviceData; import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException; import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; +import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoCoordinate; +import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoQuery; +import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoCluster; import io.entgra.device.mgt.core.device.mgt.core.TestUtils; import io.entgra.device.mgt.core.device.mgt.core.common.BaseDeviceManagementTest; import io.entgra.device.mgt.core.device.mgt.core.common.TestDataHolder; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType; +import org.apache.commons.collections.map.SingletonMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.testng.Assert; diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.extensions/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/type/template/BaseExtensionsTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.extensions/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/type/template/BaseExtensionsTest.java index adf8ade71c..cc0c9b0d8d 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.extensions/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/type/template/BaseExtensionsTest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.extensions/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/type/template/BaseExtensionsTest.java @@ -22,6 +22,7 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementEx import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.MetadataManagementServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.util.DeviceManagerUtil; @@ -126,6 +127,7 @@ public class BaseExtensionsTest { readDataSourceConfig(datasourceLocation + DATASOURCE_EXT)); DeviceManagementDAOFactory.init(dataSource); MetadataManagementDAOFactory.init(dataSource); + OperationManagementDAOFactory.init(dataSource); } protected DataSourceConfig readDataSourceConfig(String configLocation) throws DeviceManagementException { diff --git a/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf/grafana-config.xml b/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf/grafana-config.xml index f6ae22a601..e7b5a7bf3e 100644 --- a/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf/grafana-config.xml +++ b/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf/grafana-config.xml @@ -32,4 +32,10 @@ admin admin + + + true + + false + diff --git a/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf_templates.templates.repository.conf/grafana-config.xml.j2 b/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf_templates.templates.repository.conf/grafana-config.xml.j2 index 623a6cda06..dbf9d38a6e 100644 --- a/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf_templates.templates.repository.conf/grafana-config.xml.j2 +++ b/features/analytics-mgt/grafana-mgt/io.entgra.device.mgt.core.analytics.mgt.grafana.proxy.server.feature/src/main/resources/conf_templates.templates.repository.conf/grafana-config.xml.j2 @@ -32,4 +32,10 @@ admin admin + + + true + + false + diff --git a/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml b/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml index 8303fc6402..32dc388789 100644 --- a/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml +++ b/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml @@ -421,6 +421,7 @@ dm:admin:cea:delete dm:admin:cea:sync am:pub:app:upload + dm:devices:ops:status:update device-mgt