Sync with master

master
Lasantha Dharmakeerthi 4 months ago
commit 3d281de94a

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>grafana-mgt</artifactId> <artifactId>grafana-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>grafana-mgt</artifactId> <artifactId>grafana-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>grafana-mgt</artifactId> <artifactId>grafana-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>analytics-mgt</artifactId> <artifactId>analytics-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -20,7 +20,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>application-mgt</artifactId> <artifactId>application-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -25,16 +25,52 @@ public class ApplicationArtifact {
private String installerName; private String installerName;
private InputStream installerStream; private InputStream installerStream;
private String installerPath;
private String bannerName; private String bannerName;
private InputStream bannerStream; private InputStream bannerStream;
private String bannerPath;
private String iconName; private String iconName;
private InputStream iconStream; private InputStream iconStream;
private String iconPath;
private Map<String , InputStream> screenshots; private Map<String , InputStream> screenshots;
private Map<String, String> screenshotPaths;
public String getInstallerPath() {
return installerPath;
}
public void setInstallerPath(String installerPath) {
this.installerPath = installerPath;
}
public String getBannerPath() {
return bannerPath;
}
public void setBannerPath(String bannerPath) {
this.bannerPath = bannerPath;
}
public String getIconPath() {
return iconPath;
}
public void setIconPath(String iconPath) {
this.iconPath = iconPath;
}
public Map<String, String> getScreenshotPaths() {
return screenshotPaths;
}
public void setScreenshotPaths(Map<String, String> screenshotPaths) {
this.screenshotPaths = screenshotPaths;
}
public String getInstallerName() { public String getInstallerName() {
return installerName; return installerName;

@ -18,6 +18,7 @@
package io.entgra.device.mgt.core.application.mgt.common; package io.entgra.device.mgt.core.application.mgt.common;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class CategorizedSubscriptionResult { public class CategorizedSubscriptionResult {
@ -60,6 +61,33 @@ public class CategorizedSubscriptionResult {
this.subscribedDevices = subscribedDevices; this.subscribedDevices = subscribedDevices;
} }
public CategorizedSubscriptionResult(List<DeviceSubscriptionData> devices, String tabActionStatus) {
switch (tabActionStatus) {
case "COMPLETED":
this.installedDevices = devices;
break;
case "PENDING":
this.pendingDevices = devices;
break;
case "ERROR":
this.errorDevices = devices;
break;
case "NEW":
this.newDevices = devices;
break;
case "SUBSCRIBED":
this.subscribedDevices = devices;
break;
default:
this.installedDevices = new ArrayList<>();
this.pendingDevices = new ArrayList<>();
this.errorDevices = new ArrayList<>();
this.newDevices = new ArrayList<>();
this.subscribedDevices = new ArrayList<>();
break;
}
}
public List<DeviceSubscriptionData> getInstalledDevices() { public List<DeviceSubscriptionData> getInstalledDevices() {
return installedDevices; return installedDevices;
} }
@ -100,4 +128,3 @@ public class CategorizedSubscriptionResult {
this.subscribedDevices = subscribedDevices; this.subscribedDevices = subscribedDevices;
} }
} }

@ -547,5 +547,20 @@ public interface ApplicationManager {
* @throws ApplicationManagementException thrown if an error occurs when deleting data * @throws ApplicationManagementException thrown if an error occurs when deleting data
*/ */
void deleteApplicationDataOfTenant(int tenantId) throws ApplicationManagementException; void deleteApplicationDataOfTenant(int tenantId) throws ApplicationManagementException;
/**
* Delete all application related data of a tenant by tenant Domain
*
* @param tenantDomain Domain of the Tenant
* @throws ApplicationManagementException thrown if an error occurs when deleting data
*/
void deleteApplicationDataByTenantDomain(String tenantDomain) throws ApplicationManagementException; void deleteApplicationDataByTenantDomain(String tenantDomain) throws ApplicationManagementException;
/**
* Delete all Application artifacts related to a tenant by Tenant Domain
*
* @param tenantDomain Domain of the Tenant
* @throws ApplicationManagementException thrown if an error occurs when deleting app folders
*/
void deleteApplicationArtifactsByTenantDomain(String tenantDomain) throws ApplicationManagementException;
} }

@ -140,4 +140,14 @@ public interface ApplicationStorageManager {
* @throws ApplicationStorageManagementException thrown if * @throws ApplicationStorageManagementException thrown if
*/ */
void deleteAppFolderOfTenant(int tenantId) throws ApplicationStorageManagementException; void deleteAppFolderOfTenant(int tenantId) throws ApplicationStorageManagementException;
/**
* Get absolute path of a file describe by hashVal, folder, file name and tenantId
* @param hashVal Hash value of the application release.
* @param folderName Folder name file resides.
* @param fileName File name of the file.
* @param tenantId Tenant ID
* @return Absolute path
*/
String getAbsolutePathOfFile(String hashVal, String folderName, String fileName, int tenantId);
} }

@ -233,8 +233,9 @@ public interface SubscriptionManager {
* @return {@link SubscriptionsDTO} which contains the details of subscriptions. * @return {@link SubscriptionsDTO} which contains the details of subscriptions.
* @throws ApplicationManagementException if an error occurs while fetching the group details * @throws ApplicationManagementException if an error occurs while fetching the group details
*/ */
List<SubscriptionsDTO> getGroupsSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) public List<SubscriptionsDTO> getGroupsSubscriptionDetailsByUUID(String uuid, String subscriptionStatus,
throws ApplicationManagementException; PaginationRequest request, int offset,
int limit) throws ApplicationManagementException;
/** /**
* Retrieves the user details associated with a given app release UUID. * Retrieves the user details associated with a given app release UUID.
@ -246,8 +247,8 @@ public interface SubscriptionManager {
* @return {@link SubscriptionsDTO} which contains the details of subscriptions. * @return {@link SubscriptionsDTO} which contains the details of subscriptions.
* @throws ApplicationManagementException if an error occurs while fetching the user details * @throws ApplicationManagementException if an error occurs while fetching the user details
*/ */
List<SubscriptionsDTO> getUserSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) List<SubscriptionsDTO> getUserSubscriptionsByUUID(String uuid, String subscriptionStatus, PaginationRequest request,
throws ApplicationManagementException; int offset, int limit) throws ApplicationManagementException;
/** /**
* Retrieves the Role details associated with a given app release UUID. * Retrieves the Role details associated with a given app release UUID.
@ -259,8 +260,8 @@ public interface SubscriptionManager {
* @return {@link SubscriptionsDTO} which contains the details of subscriptions. * @return {@link SubscriptionsDTO} which contains the details of subscriptions.
* @throws ApplicationManagementException if an error occurs while fetching the role details * @throws ApplicationManagementException if an error occurs while fetching the role details
*/ */
List<SubscriptionsDTO> getRoleSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) List<SubscriptionsDTO> getRoleSubscriptionsByUUID(String uuid, String subscriptionStatus, PaginationRequest request,
throws ApplicationManagementException; int offset, int limit) throws ApplicationManagementException;
/** /**
* Retrieves the Device Subscription details associated with a given app release UUID. * Retrieves the Device Subscription details associated with a given app release UUID.
@ -272,8 +273,9 @@ public interface SubscriptionManager {
* @return {@link DeviceSubscriptionResponseDTO} which contains the details of device subscriptions. * @return {@link DeviceSubscriptionResponseDTO} which contains the details of device subscriptions.
* @throws ApplicationManagementException if an error occurs while fetching the device subscription details * @throws ApplicationManagementException if an error occurs while fetching the device subscription details
*/ */
DeviceSubscriptionResponseDTO getDeviceSubscriptionsDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) DeviceSubscriptionResponseDTO getDeviceSubscriptionsDetailsByUUID(String uuid, String subscriptionStatus,
throws ApplicationManagementException; PaginationRequest request, int offset,
int limit) throws ApplicationManagementException;
/** /**
* Retrieves the All Device details associated with a given app release UUID. * Retrieves the All Device details associated with a given app release UUID.
@ -285,20 +287,19 @@ public interface SubscriptionManager {
* @return {@link DeviceSubscriptionResponseDTO} which contains the details of device subscriptions. * @return {@link DeviceSubscriptionResponseDTO} which contains the details of device subscriptions.
* @throws ApplicationManagementException if an error occurs while fetching the subscription details * @throws ApplicationManagementException if an error occurs while fetching the subscription details
*/ */
DeviceSubscriptionResponseDTO getAllSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) DeviceSubscriptionResponseDTO getAllSubscriptionDetailsByUUID(String uuid, String subscriptionStatus,
throws ApplicationManagementException; PaginationRequest request, int offset,
int limit) throws ApplicationManagementException;
/** /**
* This method is responsible for retrieving device subscription details related to the given UUID. * 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 deviceId the deviceId of the device that need to get operation details.
* @param uuid the UUID of the application release. * @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. * @return {@link DeviceOperationDTO} which contains the details of device subscriptions.
* @throws SubscriptionManagementException if there is an error while fetching the details. * @throws SubscriptionManagementException if there is an error while fetching the details.
*/ */
List<DeviceOperationDTO> getSubscriptionOperationsByUUIDAndDeviceID(int deviceId, String uuid, int offset, int limit) List<DeviceOperationDTO> getSubscriptionOperationsByUUIDAndDeviceID(int deviceId, String uuid)
throws ApplicationManagementException; throws ApplicationManagementException;
/** /**

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>application-mgt</artifactId> <artifactId>application-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -99,6 +99,7 @@
io.entgra.device.mgt.core.identity.jwt.client.extension.dto;version="[5.0,6)", io.entgra.device.mgt.core.identity.jwt.client.extension.dto;version="[5.0,6)",
io.entgra.device.mgt.core.identity.jwt.client.extension.exception;version="[5.0,6)", io.entgra.device.mgt.core.identity.jwt.client.extension.exception;version="[5.0,6)",
io.entgra.device.mgt.core.identity.jwt.client.extension.service;version="[5.0,6)", io.entgra.device.mgt.core.identity.jwt.client.extension.service;version="[5.0,6)",
io.entgra.device.mgt.core.tenant.mgt.common.*;version="[5.0,6)",
javax.annotation;version="[1.0,2)", javax.annotation;version="[1.0,2)",
javax.naming, javax.naming,
javax.sql, javax.sql,
@ -443,6 +444,11 @@
<artifactId>org.wso2.carbon.tenant.mgt</artifactId> <artifactId>org.wso2.carbon.tenant.mgt</artifactId>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.tenant.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.orbit.javax.xml.bind</groupId> <groupId>org.wso2.orbit.javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>

@ -378,12 +378,10 @@ public interface SubscriptionDAO {
* @param appReleaseId the appReleaseId of the application release. * @param appReleaseId the appReleaseId of the application release.
* @param deviceId the deviceId of the device that need to get operation details. * @param deviceId the deviceId of the device that need to get operation details.
* @param tenantId id of the current tenant. * @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. * @return {@link DeviceOperationDTO} which contains the details of device subscriptions.
* @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails.
*/ */
List<DeviceOperationDTO> getSubscriptionOperationsByAppReleaseIDAndDeviceID(int appReleaseId, int deviceId, int tenantId, int offset, int limit) List<DeviceOperationDTO> getSubscriptionOperationsByAppReleaseIDAndDeviceID(int appReleaseId, int deviceId, int tenantId)
throws ApplicationManagementDAOException; throws ApplicationManagementDAOException;
/** /**
@ -392,12 +390,16 @@ public interface SubscriptionDAO {
* @param appReleaseId the appReleaseId of the application release. * @param appReleaseId the appReleaseId of the application release.
* @param unsubscribe the Status of the subscription. * @param unsubscribe the Status of the subscription.
* @param tenantId id of the current tenant. * @param tenantId id of the current tenant.
* @param actionStatus Status of the action
* @param actionType type of the action
* @param actionTriggeredBy subscribed by
* @param deviceIds deviceIds deviceIds to retrieve data. * @param deviceIds deviceIds deviceIds to retrieve data.
* @return {@link DeviceOperationDTO} which contains the details of device subscriptions. * @return {@link DeviceOperationDTO} which contains the details of device subscriptions.
* @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails.
*/ */
List<DeviceSubscriptionDTO> getSubscriptionDetailsByDeviceIds(int appReleaseId, boolean unsubscribe, int tenantId, List<Integer> deviceIds) List<DeviceSubscriptionDTO> getSubscriptionDetailsByDeviceIds(int appReleaseId, boolean unsubscribe, int tenantId,
throws ApplicationManagementDAOException; List<Integer> deviceIds, String actionStatus, String actionType,
String actionTriggeredBy, String tabActionStatus) throws ApplicationManagementDAOException;
/** /**
* This method is used to get the details of device subscriptions related to a UUID. * This method is used to get the details of device subscriptions related to a UUID.
@ -405,13 +407,16 @@ public interface SubscriptionDAO {
* @param appReleaseId the appReleaseId of the application release. * @param appReleaseId the appReleaseId of the application release.
* @param unsubscribe the Status of the subscription. * @param unsubscribe the Status of the subscription.
* @param tenantId id of the current tenant. * @param tenantId id of the current tenant.
* @param actionStatus Status of the action
* @param actionType type of the action
* @param actionTriggeredBy subscribed by
* @param offset the offset for the data set * @param offset the offset for the data set
* @param limit the limit for the data set * @param limit the limit for the data set
* @return {@link DeviceOperationDTO} which contains the details of device subscriptions. * @return {@link DeviceOperationDTO} which contains the details of device subscriptions.
* @throws ApplicationManagementDAOException if connection establishment or SQL execution fails. * @throws ApplicationManagementDAOException if connection establishment or SQL execution fails.
*/ */
List<DeviceSubscriptionDTO> getAllSubscriptionsDetails(int appReleaseId, boolean unsubscribe, int tenantId, int offset, int limit) List<DeviceSubscriptionDTO> getAllSubscriptionsDetails(int appReleaseId, boolean unsubscribe, int tenantId, String actionStatus, String actionType,
throws ApplicationManagementDAOException; String actionTriggeredBy, int offset, int limit) throws ApplicationManagementDAOException;
/** /**
* This method is used to get the counts of all subscription types related to a UUID. * This method is used to get the counts of all subscription types related to a UUID.

@ -1858,7 +1858,7 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
@Override @Override
public List<DeviceOperationDTO> getSubscriptionOperationsByAppReleaseIDAndDeviceID( public List<DeviceOperationDTO> getSubscriptionOperationsByAppReleaseIDAndDeviceID(
int appReleaseId, int deviceId, int tenantId, int offset, int limit) throws ApplicationManagementDAOException { int appReleaseId, int deviceId, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get device subscriptions related to the given AppReleaseID and DeviceID."); log.debug("Request received in DAO Layer to get device subscriptions related to the given AppReleaseID and DeviceID.");
} }
@ -1878,13 +1878,12 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
"WHERE ads.AP_APP_RELEASE_ID = ? " + "WHERE ads.AP_APP_RELEASE_ID = ? " +
"AND ads.DM_DEVICE_ID = ? " + "AND ads.DM_DEVICE_ID = ? " +
"AND ads.TENANT_ID = ? " + "AND ads.TENANT_ID = ? " +
"LIMIT ? OFFSET ?"; "ORDER BY aasom.OPERATION_ID DESC " +
"LIMIT 1";
try (PreparedStatement ps = conn.prepareStatement(sql)) { try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, appReleaseId); ps.setInt(1, appReleaseId);
ps.setInt(2, deviceId); ps.setInt(2, deviceId);
ps.setInt(3, tenantId); ps.setInt(3, tenantId);
ps.setInt(4, limit);
ps.setInt(5, offset);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
DeviceOperationDTO deviceSubscription; DeviceOperationDTO deviceSubscription;
while (rs.next()) { while (rs.next()) {
@ -1913,8 +1912,9 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
} }
@Override @Override
public List<DeviceSubscriptionDTO> getSubscriptionDetailsByDeviceIds(int appReleaseId, boolean unsubscribe, int tenantId, List<Integer> deviceIds) public List<DeviceSubscriptionDTO> getSubscriptionDetailsByDeviceIds(int appReleaseId, boolean unsubscribe, int tenantId,
throws ApplicationManagementDAOException { List<Integer> deviceIds, String actionStatus, String actionType,
String actionTriggeredBy, String tabActionStatus) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Getting device subscriptions for the application release id " + appReleaseId log.debug("Getting device subscriptions for the application release id " + appReleaseId
+ " and device ids " + deviceIds + " from the database"); + " and device ids " + deviceIds + " from the database");
@ -1922,7 +1922,7 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
try { try {
Connection conn = this.getDBConnection(); Connection conn = this.getDBConnection();
String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP"; String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP";
String sql = "SELECT " StringBuilder sql = new StringBuilder("SELECT "
+ "DS.ID AS ID, " + "DS.ID AS ID, "
+ "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, " + "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, "
+ "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, " + "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, "
@ -1934,16 +1934,39 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
+ "DS.DM_DEVICE_ID AS DEVICE_ID " + "DS.DM_DEVICE_ID AS DEVICE_ID "
+ "FROM AP_DEVICE_SUBSCRIPTION DS " + "FROM AP_DEVICE_SUBSCRIPTION DS "
+ "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.UNSUBSCRIBED = ? AND DS.TENANT_ID = ? AND DS.DM_DEVICE_ID IN (" + + "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(",")) + ") " deviceIds.stream().map(id -> "?").collect(Collectors.joining(",")) + ") ");
+ "ORDER BY " + subscriptionStatusTime + " DESC";
try (PreparedStatement ps = conn.prepareStatement(sql)) { if (actionStatus != null && !actionStatus.isEmpty()) {
ps.setInt(1, appReleaseId); sql.append(" AND DS.STATUS = ? ");
ps.setBoolean(2, unsubscribe); }
ps.setInt(3, tenantId); if (actionType != null && !actionType.isEmpty()) {
sql.append(" AND DS.ACTION_TRIGGERED_FROM = ? ");
}
if (actionTriggeredBy != null && !actionTriggeredBy.isEmpty()) {
sql.append(" AND DS.SUBSCRIBED_BY LIKE ? ");
}
sql.append("ORDER BY ").append(subscriptionStatusTime).append(" DESC");
try (PreparedStatement ps = conn.prepareStatement(sql.toString())) {
int paramIdx = 1;
ps.setInt(paramIdx++, appReleaseId);
ps.setBoolean(paramIdx++, unsubscribe);
ps.setInt(paramIdx++, tenantId);
for (int i = 0; i < deviceIds.size(); i++) { for (int i = 0; i < deviceIds.size(); i++) {
ps.setInt(4 + i, deviceIds.get(i)); ps.setInt(paramIdx++, deviceIds.get(i));
} }
if (actionStatus != null && !actionStatus.isEmpty()) {
ps.setString(paramIdx++, actionStatus);
}
if (actionType != null && !actionType.isEmpty()) {
ps.setString(paramIdx++, actionType);
}
if (actionTriggeredBy != null && !actionTriggeredBy.isEmpty()) {
ps.setString(paramIdx++, "%" + actionTriggeredBy + "%");
}
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Successfully retrieved device subscriptions for application release id " log.debug("Successfully retrieved device subscriptions for application release id "
@ -1982,6 +2005,7 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
@Override @Override
public List<DeviceSubscriptionDTO> getAllSubscriptionsDetails(int appReleaseId, boolean unsubscribe, int tenantId, public List<DeviceSubscriptionDTO> getAllSubscriptionsDetails(int appReleaseId, boolean unsubscribe, int tenantId,
String actionStatus, String actionType, String actionTriggeredBy,
int offset, int limit) throws ApplicationManagementDAOException { int offset, int limit) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Getting device subscriptions for the application release id " + appReleaseId log.debug("Getting device subscriptions for the application release id " + appReleaseId
@ -1989,7 +2013,8 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
} }
String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP"; String subscriptionStatusTime = unsubscribe ? "DS.UNSUBSCRIBED_TIMESTAMP" : "DS.SUBSCRIBED_TIMESTAMP";
String sql = "SELECT " String actionTriggeredColumn = unsubscribe ? "DS.UNSUBSCRIBED_BY" : "DS.SUBSCRIBED_BY";
StringBuilder sql = new StringBuilder("SELECT "
+ "DS.ID AS ID, " + "DS.ID AS ID, "
+ "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, " + "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, "
+ "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, " + "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, "
@ -1997,21 +2022,45 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
+ "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, " + "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, "
+ "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, " + "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, "
+ "DS.ACTION_TRIGGERED_FROM AS ACTION_TRIGGERED_FROM, " + "DS.ACTION_TRIGGERED_FROM AS ACTION_TRIGGERED_FROM, "
+ "DS.STATUS AS STATUS," + "DS.STATUS AS STATUS, "
+ "DS.DM_DEVICE_ID AS DEVICE_ID " + "DS.DM_DEVICE_ID AS DEVICE_ID "
+ "FROM AP_DEVICE_SUBSCRIPTION DS " + "FROM AP_DEVICE_SUBSCRIPTION DS "
+ "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.UNSUBSCRIBED = ? AND DS.TENANT_ID=? " + "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.UNSUBSCRIBED = ? AND DS.TENANT_ID = ? ");
+ "ORDER BY " + subscriptionStatusTime + " DESC "
+ "LIMIT ? OFFSET ?"; if (actionStatus != null && !actionStatus.isEmpty()) {
sql.append(" AND DS.STATUS = ? ");
}
if (actionType != null && !actionType.isEmpty()) {
sql.append(" AND DS.ACTION_TRIGGERED_FROM = ? ");
}
if (actionTriggeredBy != null && !actionTriggeredBy.isEmpty()) {
sql.append(" AND ").append(actionTriggeredColumn).append(" LIKE ? ");
}
sql.append("ORDER BY ").append(subscriptionStatusTime).append(" DESC ")
.append("LIMIT ? OFFSET ?");
try { try {
Connection conn = this.getDBConnection(); Connection conn = this.getDBConnection();
try (PreparedStatement ps = conn.prepareStatement(sql)) { try (PreparedStatement ps = conn.prepareStatement(sql.toString())) {
ps.setInt(1, appReleaseId); int paramIdx = 1;
ps.setBoolean(2, unsubscribe); ps.setInt(paramIdx++, appReleaseId);
ps.setInt(3, tenantId); ps.setBoolean(paramIdx++, unsubscribe);
ps.setInt(4, limit); ps.setInt(paramIdx++, tenantId);
ps.setInt(5, offset);
if (actionStatus != null && !actionStatus.isEmpty()) {
ps.setString(paramIdx++, actionStatus);
}
if (actionType != null && !actionType.isEmpty()) {
ps.setString(paramIdx++, actionType);
}
if (actionTriggeredBy != null && !actionTriggeredBy.isEmpty()) {
ps.setString(paramIdx++, "%" + actionTriggeredBy + "%");
}
ps.setInt(paramIdx++, limit);
ps.setInt(paramIdx++, offset);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Successfully retrieved device subscriptions for application release id " log.debug("Successfully retrieved device subscriptions for application release id "
@ -2042,7 +2091,7 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e); throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) { } catch (SQLException e) {
String msg = "Error occurred while while running SQL to get device subscription data for application ID: " + appReleaseId; String msg = "Error occurred while running SQL to get device subscription data for application ID: " + appReleaseId;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e); throw new ApplicationManagementDAOException(msg, e);
} }

@ -19,28 +19,11 @@
package io.entgra.device.mgt.core.application.mgt.core.impl; package io.entgra.device.mgt.core.application.mgt.core.impl;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileDownloaderServiceException; import io.entgra.device.mgt.core.application.mgt.common.exception.FileDownloaderServiceException;
import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferServiceException;
import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException; import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException;
import io.entgra.device.mgt.core.application.mgt.core.dao.*; import io.entgra.device.mgt.core.application.mgt.core.dao.*;
import io.entgra.device.mgt.core.application.mgt.core.exception.*; import io.entgra.device.mgt.core.application.mgt.core.exception.*;
import io.entgra.device.mgt.core.device.mgt.common.Base64File;
import io.entgra.device.mgt.core.application.mgt.core.dao.SPApplicationDAO; import io.entgra.device.mgt.core.application.mgt.core.dao.SPApplicationDAO;
import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil; import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil;
import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.validator.routines.UrlValidator;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationArtifact; import io.entgra.device.mgt.core.application.mgt.common.ApplicationArtifact;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstaller; import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstaller;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationList; import io.entgra.device.mgt.core.application.mgt.common.ApplicationList;
@ -91,21 +74,35 @@ import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateMa
import io.entgra.device.mgt.core.application.mgt.core.util.APIUtil; import io.entgra.device.mgt.core.application.mgt.core.util.APIUtil;
import io.entgra.device.mgt.core.application.mgt.core.util.ConnectionManagerUtil; import io.entgra.device.mgt.core.application.mgt.core.util.ConnectionManagerUtil;
import io.entgra.device.mgt.core.application.mgt.core.util.Constants; import io.entgra.device.mgt.core.application.mgt.core.util.Constants;
import io.entgra.device.mgt.core.device.mgt.common.Base64File;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
import io.entgra.device.mgt.core.device.mgt.core.common.exception.StorageManagementException; import io.entgra.device.mgt.core.device.mgt.core.common.exception.StorageManagementException;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.stratos.common.beans.TenantInfoBean; import io.entgra.device.mgt.core.tenant.mgt.common.exception.TenantMgtException;
import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.validator.routines.UrlValidator;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -722,24 +719,29 @@ public class ApplicationManagerImpl implements ApplicationManager {
* @throws ResourceManagementException if error occurred while uploading * @throws ResourceManagementException if error occurred while uploading
*/ */
private ApplicationReleaseDTO uploadCustomAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, ApplicationArtifact applicationArtifact, private ApplicationReleaseDTO uploadCustomAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, ApplicationArtifact applicationArtifact,
String deviceType) String deviceType)
throws ResourceManagementException, ApplicationManagementException { throws ResourceManagementException, ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager();
byte[] content = getByteContentOfApp(applicationArtifact); try {
String md5OfApp = generateMD5OfApp(applicationArtifact, content); String md5OfApp = applicationStorageManager.
validateReleaseBinaryFileHash(md5OfApp); getMD5(Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())));
releaseDTO.setUuid(UUID.randomUUID().toString()); validateReleaseBinaryFileHash(md5OfApp);
releaseDTO.setAppHashValue(md5OfApp); releaseDTO.setUuid(UUID.randomUUID().toString());
releaseDTO.setInstallerName(applicationArtifact.getInstallerName()); releaseDTO.setAppHashValue(md5OfApp);
releaseDTO.setInstallerName(applicationArtifact.getInstallerName());
try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) {
applicationStorageManager.uploadReleaseArtifact(releaseDTO, deviceType, applicationStorageManager.uploadReleaseArtifact(releaseDTO, deviceType,
binaryDuplicate, tenantId); Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())), tenantId);
} catch (IOException e) { } catch (IOException e) {
String msg = "Error occurred when uploading release artifact into the server"; String msg = "Error occurred when uploading release artifact into the server";
log.error(msg); log.error(msg);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (StorageManagementException e) {
String msg = "Error occurred while md5sum value retrieving process: application UUID "
+ releaseDTO.getUuid();
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} }
return addImageArtifacts(releaseDTO, applicationArtifact, tenantId); return addImageArtifacts(releaseDTO, applicationArtifact, tenantId);
} }
@ -768,6 +770,8 @@ public class ApplicationManagerImpl implements ApplicationManager {
return Constants.GOOGLE_PLAY_STORE_URL; return Constants.GOOGLE_PLAY_STORE_URL;
} else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) { } else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) {
return Constants.APPLE_STORE_URL; return Constants.APPLE_STORE_URL;
} else if (DeviceTypes.WINDOWS.toString().equalsIgnoreCase(deviceType)) {
return Constants.MICROSOFT_STORE_URL;
} else { } else {
throw new IllegalArgumentException("No such device with the name " + deviceType); throw new IllegalArgumentException("No such device with the name " + deviceType);
} }
@ -855,82 +859,77 @@ public class ApplicationManagerImpl implements ApplicationManager {
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
applicationReleaseDTO.setUuid(uuid); applicationReleaseDTO.setUuid(uuid);
// The application executable artifacts such as apks are uploaded. // The application executable artifacts such as apks are uploaded.
try { try {
byte[] content = IOUtils.toByteArray(applicationArtifact.getInstallerStream());
applicationReleaseDTO.setInstallerName(applicationArtifact.getInstallerName()); applicationReleaseDTO.setInstallerName(applicationArtifact.getInstallerName());
try (ByteArrayInputStream binary = new ByteArrayInputStream(content)) { if (!DeviceTypes.WINDOWS.toString().equalsIgnoreCase(deviceType)) {
if (!DeviceTypes.WINDOWS.toString().equalsIgnoreCase(deviceType)) { ApplicationInstaller applicationInstaller = applicationStorageManager
ApplicationInstaller applicationInstaller = applicationStorageManager .getAppInstallerData(Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())), deviceType);
.getAppInstallerData(binary, deviceType); applicationReleaseDTO.setVersion(applicationInstaller.getVersion());
applicationReleaseDTO.setVersion(applicationInstaller.getVersion()); applicationReleaseDTO.setPackageName(applicationInstaller.getPackageName());
applicationReleaseDTO.setPackageName(applicationInstaller.getPackageName()); } else {
} else { String windowsInstallerName = applicationArtifact.getInstallerName();
String windowsInstallerName = applicationArtifact.getInstallerName(); String extension = windowsInstallerName.substring(windowsInstallerName.lastIndexOf(".") + 1);
String extension = windowsInstallerName.substring(windowsInstallerName.lastIndexOf(".") + 1); if (!extension.equalsIgnoreCase(Constants.MSI) &&
if (!extension.equalsIgnoreCase(Constants.MSI) && !extension.equalsIgnoreCase(Constants.APPX)) {
!extension.equalsIgnoreCase(Constants.APPX)) { String msg = "Application Type doesn't match with supporting application types of " +
String msg = "Application Type doesn't match with supporting application types of " + deviceType + "platform which are APPX and MSI";
deviceType + "platform which are APPX and MSI"; log.error(msg);
log.error(msg); throw new BadRequestException(msg);
throw new BadRequestException(msg);
}
} }
}
String packageName = applicationReleaseDTO.getPackageName(); String packageName = applicationReleaseDTO.getPackageName();
try { try {
ConnectionManagerUtil.openDBConnection(); ConnectionManagerUtil.openDBConnection();
if (!isNewRelease && applicationReleaseDAO if (!isNewRelease && applicationReleaseDAO
.isActiveReleaseExisitForPackageName(packageName, tenantId, .isActiveReleaseExisitForPackageName(packageName, tenantId,
lifecycleStateManager.getEndState())) { lifecycleStateManager.getEndState())) {
String msg = "Application release is already exist for the package name: " + packageName String msg = "Application release is already exist for the package name: " + packageName
+ ". Either you can delete all application releases for package " + packageName + " or " + ". Either you can delete all application releases for package " + packageName + " or "
+ "you can add this app release as an new application release, under the existing " + "you can add this app release as an new application release, under the existing "
+ "application."; + "application.";
log.error(msg); log.error(msg);
throw new ApplicationManagementException(msg); throw new ApplicationManagementException(msg);
} }
String md5OfApp = applicationStorageManager.getMD5(new ByteArrayInputStream(content)); String md5OfApp = applicationStorageManager.
if (md5OfApp == null) { getMD5(Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())));
String msg = "Error occurred while md5sum value retrieving process: application UUID " if (md5OfApp == null) {
+ applicationReleaseDTO.getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg);
}
if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) {
String msg =
"Application release exists for the uploaded binary file. Device Type: " + deviceType;
log.error(msg);
throw new BadRequestException(msg);
}
applicationReleaseDTO.setAppHashValue(md5OfApp);
try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) {
applicationStorageManager
.uploadReleaseArtifact(applicationReleaseDTO, deviceType, binaryDuplicate, tenantId);
}
} catch (StorageManagementException e) {
String msg = "Error occurred while md5sum value retrieving process: application UUID " String msg = "Error occurred while md5sum value retrieving process: application UUID "
+ applicationReleaseDTO.getUuid(); + applicationReleaseDTO.getUuid();
log.error(msg, e); log.error(msg);
throw new ApplicationStorageManagementException(msg, e); throw new ApplicationStorageManagementException(msg);
} catch (DBConnectionException e) { }
String msg = "Error occurred when getting database connection for verifying app release data."; if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) {
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg = String msg =
"Error occurred when executing the query for verifying application release existence for " "Application release exists for the uploaded binary file. Device Type: " + deviceType;
+ "the package."; log.error(msg);
log.error(msg, e); throw new BadRequestException(msg);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
} }
applicationReleaseDTO.setAppHashValue(md5OfApp);
applicationStorageManager
.uploadReleaseArtifact(applicationReleaseDTO, deviceType,
Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())), tenantId);
} catch (StorageManagementException e) {
String msg = "Error occurred while md5sum value retrieving process: application UUID "
+ applicationReleaseDTO.getUuid();
log.error(msg, e);
throw new ApplicationStorageManagementException(msg, e);
} catch (DBConnectionException e) {
String msg = "Error occurred when getting database connection for verifying app release data.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg =
"Error occurred when executing the query for verifying application release existence for "
+ "the package.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
} }
} catch (IOException e) { } catch (IOException e) {
String msg = "Error occurred when getting byte array of binary file. Installer name: " + applicationArtifact String msg = "Error occurred when getting file input stream. Installer name: " + applicationArtifact
.getInstallerName(); .getInstallerName();
log.error(msg, e); log.error(msg, e);
throw new ApplicationStorageManagementException(msg, e); throw new ApplicationStorageManagementException(msg, e);
@ -956,73 +955,64 @@ public class ApplicationManagerImpl implements ApplicationManager {
// The application executable artifacts such as apks are uploaded. // The application executable artifacts such as apks are uploaded.
try { try {
byte[] content = IOUtils.toByteArray(applicationArtifact.getInstallerStream()); String md5OfApp = applicationStorageManager.getMD5(Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())));
if (md5OfApp == null) {
try (ByteArrayInputStream binaryClone = new ByteArrayInputStream(content)) { String msg = "Error occurred while retrieving md5sum value from the binary file for application "
String md5OfApp = applicationStorageManager.getMD5(binaryClone); + "release UUID " + applicationReleaseDTO.getUuid();
log.error(msg);
if (md5OfApp == null) { throw new ApplicationStorageManagementException(msg);
String msg = "Error occurred while retrieving md5sum value from the binary file for application " }
+ "release UUID " + applicationReleaseDTO.getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg);
}
if (!applicationReleaseDTO.getAppHashValue().equals(md5OfApp)) {
applicationReleaseDTO.setInstallerName(applicationArtifact.getInstallerName());
try (ByteArrayInputStream binary = new ByteArrayInputStream(content)) {
ApplicationInstaller applicationInstaller = applicationStorageManager
.getAppInstallerData(binary, deviceType);
String packageName = applicationInstaller.getPackageName();
try { if (!applicationReleaseDTO.getAppHashValue().equals(md5OfApp)) {
ConnectionManagerUtil.getDBConnection(); applicationReleaseDTO.setInstallerName(applicationArtifact.getInstallerName());
if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) { ApplicationInstaller applicationInstaller = applicationStorageManager
String msg = "Same binary file is in the server. Hence you can't add same file into the " .getAppInstallerData(Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())), deviceType);
+ "server. Device Type: " + deviceType + " and package name: " + packageName; String packageName = applicationInstaller.getPackageName();
log.error(msg);
throw new BadRequestException(msg);
}
if (applicationReleaseDTO.getPackageName() == null){
String msg = "Found null value for application release package name for application "
+ "release which has UUID: " + applicationReleaseDTO.getUuid();
log.error(msg);
throw new ApplicationManagementException(msg);
}
if (!applicationReleaseDTO.getPackageName().equals(packageName)){
String msg = "Package name of the new artifact does not match with the package name of "
+ "the exiting application release. Package name of the existing app release "
+ applicationReleaseDTO.getPackageName() + " and package name of the new "
+ "application release " + packageName;
log.error(msg);
throw new BadRequestException(msg);
}
applicationReleaseDTO.setVersion(applicationInstaller.getVersion()); try {
applicationReleaseDTO.setPackageName(packageName); ConnectionManagerUtil.getDBConnection();
String deletingAppHashValue = applicationReleaseDTO.getAppHashValue(); if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) {
applicationReleaseDTO.setAppHashValue(md5OfApp); String msg = "Same binary file is in the server. Hence you can't add same file into the "
try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) { + "server. Device Type: " + deviceType + " and package name: " + packageName;
applicationStorageManager log.error(msg);
.uploadReleaseArtifact(applicationReleaseDTO, deviceType, binaryDuplicate, throw new BadRequestException(msg);
tenantId);
applicationStorageManager.copyImageArtifactsAndDeleteInstaller(deletingAppHashValue,
applicationReleaseDTO, tenantId);
}
} catch (DBConnectionException e) {
String msg = "Error occurred when getting database connection for verifying application "
+ "release existing for new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg = "Error occurred when executing the query for verifying application release "
+ "existence for the new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
} }
if (applicationReleaseDTO.getPackageName() == null) {
String msg = "Found null value for application release package name for application "
+ "release which has UUID: " + applicationReleaseDTO.getUuid();
log.error(msg);
throw new ApplicationManagementException(msg);
}
if (!applicationReleaseDTO.getPackageName().equals(packageName)) {
String msg = "Package name of the new artifact does not match with the package name of "
+ "the exiting application release. Package name of the existing app release "
+ applicationReleaseDTO.getPackageName() + " and package name of the new "
+ "application release " + packageName;
log.error(msg);
throw new BadRequestException(msg);
}
applicationReleaseDTO.setVersion(applicationInstaller.getVersion());
applicationReleaseDTO.setPackageName(packageName);
String deletingAppHashValue = applicationReleaseDTO.getAppHashValue();
applicationReleaseDTO.setAppHashValue(md5OfApp);
applicationStorageManager.uploadReleaseArtifact(applicationReleaseDTO, deviceType,
Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())),
tenantId);
applicationStorageManager.copyImageArtifactsAndDeleteInstaller(deletingAppHashValue,
applicationReleaseDTO, tenantId);
} catch (DBConnectionException e) {
String msg = "Error occurred when getting database connection for verifying application "
+ "release existing for new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg = "Error occurred when executing the query for verifying application release "
+ "existence for the new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
} }
} }
} catch (StorageManagementException e) { } catch (StorageManagementException e) {
@ -1031,7 +1021,7 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg, e); log.error(msg, e);
throw new ApplicationStorageManagementException(msg, e); throw new ApplicationStorageManagementException(msg, e);
} catch (IOException e) { } catch (IOException e) {
String msg = "Error occurred when getting byte array of binary file. Installer name: " + applicationArtifact String msg = "Error occurred when getting file input stream. Installer name: " + applicationArtifact
.getInstallerName(); .getInstallerName();
log.error(msg, e); log.error(msg, e);
throw new ApplicationStorageManagementException(msg, e); throw new ApplicationStorageManagementException(msg, e);
@ -3605,52 +3595,49 @@ public class ApplicationManagerImpl implements ApplicationManager {
DeviceType deviceTypeObj = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); DeviceType deviceTypeObj = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
// The application executable artifacts such as deb are uploaded. // The application executable artifacts such as deb are uploaded.
try { try {
byte[] content = IOUtils.toByteArray(applicationArtifact.getInstallerStream()); String md5OfApp = applicationStorageManager.getMD5(
try (ByteArrayInputStream binaryClone = new ByteArrayInputStream(content)) { Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())));
String md5OfApp = applicationStorageManager.getMD5(binaryClone); if (md5OfApp == null) {
if (md5OfApp == null) { String msg = "Error occurred while retrieving md5sum value from the binary file for "
String msg = "Error occurred while retrieving md5sum value from the binary file for " + "application release UUID " + applicationReleaseDTO.get().getUuid();
+ "application release UUID " + applicationReleaseDTO.get().getUuid(); log.error(msg);
log.error(msg); throw new ApplicationStorageManagementException(msg);
throw new ApplicationStorageManagementException(msg); }
}
if (!applicationReleaseDTO.get().getAppHashValue().equals(md5OfApp)) {
try {
ConnectionManagerUtil.getDBConnection();
if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) {
String msg =
"Same binary file is in the server. Hence you can't add same file into the "
+ "server. Device Type: " + deviceTypeObj.getName()
+ " and package name: " + applicationDTO.getApplicationReleaseDTOs()
.get(0).getPackageName();
log.error(msg);
throw new BadRequestException(msg);
}
applicationReleaseDTO.get().setInstallerName(applicationArtifact.getInstallerName()); if (!applicationReleaseDTO.get().getAppHashValue().equals(md5OfApp)) {
String deletingAppHashValue = applicationReleaseDTO.get().getAppHashValue(); try {
applicationReleaseDTO.get().setAppHashValue(md5OfApp); ConnectionManagerUtil.getDBConnection();
try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) { if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) {
applicationStorageManager
.uploadReleaseArtifact(applicationReleaseDTO.get(), deviceTypeObj.getName(),
binaryDuplicate, tenantId);
applicationStorageManager.copyImageArtifactsAndDeleteInstaller(deletingAppHashValue,
applicationReleaseDTO.get(), tenantId);
}
} catch (DBConnectionException e) {
String msg = "Error occurred when getting database connection for verifying application"
+ " release existing for new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg = String msg =
"Error occurred when executing the query for verifying application release " "Same binary file is in the server. Hence you can't add same file into the "
+ "existence for the new app hash value."; + "server. Device Type: " + deviceTypeObj.getName()
log.error(msg, e); + " and package name: " + applicationDTO.getApplicationReleaseDTOs()
throw new ApplicationManagementException(msg, e); .get(0).getPackageName();
} finally { log.error(msg);
ConnectionManagerUtil.closeDBConnection(); throw new BadRequestException(msg);
} }
applicationReleaseDTO.get().setInstallerName(applicationArtifact.getInstallerName());
String deletingAppHashValue = applicationReleaseDTO.get().getAppHashValue();
applicationReleaseDTO.get().setAppHashValue(md5OfApp);
applicationStorageManager.
uploadReleaseArtifact(applicationReleaseDTO.get(), deviceTypeObj.getName(),
Files.newInputStream(Paths.get(applicationArtifact.getInstallerPath())), tenantId);
applicationStorageManager.copyImageArtifactsAndDeleteInstaller(deletingAppHashValue,
applicationReleaseDTO.get(), tenantId);
} catch (DBConnectionException e) {
String msg = "Error occurred when getting database connection for verifying application"
+ " release existing for new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg =
"Error occurred when executing the query for verifying application release "
+ "existence for the new app hash value.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
} }
} }
} catch (StorageManagementException e) { } catch (StorageManagementException e) {
@ -4422,7 +4409,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
spApplicationDAO.deleteSPApplicationMappingByTenant(tenantId); spApplicationDAO.deleteSPApplicationMappingByTenant(tenantId);
spApplicationDAO.deleteIdentityServerByTenant(tenantId); spApplicationDAO.deleteIdentityServerByTenant(tenantId);
applicationDAO.deleteApplicationsByTenant(tenantId); applicationDAO.deleteApplicationsByTenant(tenantId);
APIUtil.getApplicationStorageManager().deleteAppFolderOfTenant(tenantId);
ConnectionManagerUtil.commitDBTransaction(); ConnectionManagerUtil.commitDBTransaction();
} catch (DBConnectionException e) { } catch (DBConnectionException e) {
@ -4447,12 +4433,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ " of tenant ID: " + tenantId ; + " of tenant ID: " + tenantId ;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (ApplicationStorageManagementException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting App folder of tenant"
+ " of tenant ID: " + tenantId ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally { } finally {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.closeDBConnection();
} }
@ -4461,19 +4441,9 @@ public class ApplicationManagerImpl implements ApplicationManager {
@Override @Override
public void deleteApplicationDataByTenantDomain(String tenantDomain) throws ApplicationManagementException { public void deleteApplicationDataByTenantDomain(String tenantDomain) throws ApplicationManagementException {
int tenantId; int tenantId;
try{
TenantMgtAdminService tenantMgtAdminService = new TenantMgtAdminService();
TenantInfoBean tenantInfoBean = tenantMgtAdminService.getTenant(tenantDomain);
tenantId = tenantInfoBean.getTenantId();
} catch (Exception e) {
String msg = "Error getting tenant ID from domain: "
+ tenantDomain;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
try { try {
tenantId = DataHolder.getInstance().getTenantManagerAdminService().getTenantId(tenantDomain);
ConnectionManagerUtil.beginDBTransaction(); ConnectionManagerUtil.beginDBTransaction();
vppApplicationDAO.deleteAssociationByTenant(tenantId); vppApplicationDAO.deleteAssociationByTenant(tenantId);
@ -4497,40 +4467,54 @@ public class ApplicationManagerImpl implements ApplicationManager {
spApplicationDAO.deleteSPApplicationMappingByTenant(tenantId); spApplicationDAO.deleteSPApplicationMappingByTenant(tenantId);
spApplicationDAO.deleteIdentityServerByTenant(tenantId); spApplicationDAO.deleteIdentityServerByTenant(tenantId);
applicationDAO.deleteApplicationsByTenant(tenantId); applicationDAO.deleteApplicationsByTenant(tenantId);
APIUtil.getApplicationStorageManager().deleteAppFolderOfTenant(tenantId);
ConnectionManagerUtil.commitDBTransaction(); ConnectionManagerUtil.commitDBTransaction();
} catch (DBConnectionException e) { } catch (DBConnectionException e) {
String msg = "Error occurred while observing the database connection to delete applications for tenant with ID: " String msg = "Error occurred while observing the database connection to delete applications for tenant with " +
+ tenantId; "domain: " + tenantDomain;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction(); ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Database access error is occurred when getting applications for tenant with ID: " + tenantId; String msg = "Database access error is occurred when getting applications for tenant with domain: "
+ tenantDomain;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (LifeCycleManagementDAOException e) { } catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction(); ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting life-cycle state data of application releases of the tenant" String msg = "Error occurred while deleting life-cycle state data of application releases of the tenant"
+ " of ID: " + tenantId ; + " of domain: " + tenantDomain ;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (ReviewManagementDAOException e) { } catch (ReviewManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction(); ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred while deleting reviews of application releases of the applications" String msg = "Error occurred while deleting reviews of application releases of the applications"
+ " of tenant ID: " + tenantId ; + " of tenant of domain: " + tenantDomain ;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (ApplicationStorageManagementException e) { } catch (Exception e) {
ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error getting tenant ID from domain: "
String msg = "Error occurred while deleting App folder of tenant" + tenantDomain;
+ " of tenant ID: " + tenantId ;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
} }
}
@Override
public void deleteApplicationArtifactsByTenantDomain(String tenantDomain) throws ApplicationManagementException {
int tenantId;
try {
tenantId = DataHolder.getInstance().getTenantManagerAdminService().getTenantId(tenantDomain);
DataHolder.getInstance().getApplicationStorageManager().deleteAppFolderOfTenant(tenantId);
} catch (ApplicationStorageManagementException e) {
String msg = "Error deleting app artifacts of tenant of domain: " + tenantDomain ;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (TenantMgtException e) {
String msg = "Error getting tenant ID from domain: "
+ tenantDomain + " when trying to delete application artifacts of tenant";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
} }
} }

@ -32,14 +32,13 @@ import io.entgra.device.mgt.core.device.mgt.core.common.exception.StorageManagem
import io.entgra.device.mgt.core.device.mgt.core.common.util.StorageManagementUtil; import io.entgra.device.mgt.core.device.mgt.core.common.util.StorageManagementUtil;
import net.dongliu.apk.parser.bean.ApkMeta; import net.dongliu.apk.parser.bean.ApkMeta;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Paths;
import java.util.List; import java.util.List;
import static io.entgra.device.mgt.core.device.mgt.core.common.util.StorageManagementUtil.saveFile; import static io.entgra.device.mgt.core.device.mgt.core.common.util.StorageManagementUtil.saveFile;
@ -158,13 +157,12 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
public void uploadReleaseArtifact(ApplicationReleaseDTO applicationReleaseDTO, public void uploadReleaseArtifact(ApplicationReleaseDTO applicationReleaseDTO,
String deviceType, InputStream binaryFile, int tenantId) throws ResourceManagementException { String deviceType, InputStream binaryFile, int tenantId) throws ResourceManagementException {
try { try {
byte [] content = IOUtils.toByteArray(binaryFile);
String artifactDirectoryPath = String artifactDirectoryPath =
storagePath + tenantId + File.separator + applicationReleaseDTO.getAppHashValue() + File.separator storagePath + tenantId + File.separator + applicationReleaseDTO.getAppHashValue() + File.separator
+ Constants.APP_ARTIFACT; + Constants.APP_ARTIFACT;
StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath); StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
String artifactPath = artifactDirectoryPath + File.separator + applicationReleaseDTO.getInstallerName(); String artifactPath = artifactDirectoryPath + File.separator + applicationReleaseDTO.getInstallerName();
saveFile(new ByteArrayInputStream(content), artifactPath); saveFile(binaryFile, artifactPath);
} catch (IOException e) { } catch (IOException e) {
String msg = "IO Exception while saving the release artifacts in the server for the application UUID " String msg = "IO Exception while saving the release artifacts in the server for the application UUID "
+ applicationReleaseDTO.getUuid(); + applicationReleaseDTO.getUuid();
@ -327,4 +325,12 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
} }
} }
} }
@Override
public String getAbsolutePathOfFile(String hashVal, String folderName, String fileName, int tenantId) {
String filePath =
storagePath + tenantId + File.separator + hashVal + File.separator + folderName + File.separator
+ fileName;
return Paths.get(filePath).toAbsolutePath().toString();
}
} }

@ -31,6 +31,7 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.NotFoundException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
@ -103,8 +104,13 @@ public class FileTransferServiceImpl implements FileTransferService {
@Override @Override
public boolean isExistsOnLocal(URL downloadUrl) throws FileTransferServiceException { public boolean isExistsOnLocal(URL downloadUrl) throws FileTransferServiceException {
try { try {
return FileTransferServiceHelperUtil.resolve(downloadUrl) != null; FileDescriptor fileDescriptor = FileTransferServiceHelperUtil.resolve(downloadUrl);
} catch (FileTransferServiceHelperUtilException e) { if (fileDescriptor != null && fileDescriptor.getFile() != null) {
fileDescriptor.getFile().close();
return true;
}
return false;
} catch (FileTransferServiceHelperUtilException | IOException e) {
String msg = "Error occurred while checking the existence of artifact on the local environment"; String msg = "Error occurred while checking the existence of artifact on the local environment";
log.error(msg, e); log.error(msg, e);
throw new FileTransferServiceException(msg, e); throw new FileTransferServiceException(msg, e);

@ -1734,12 +1734,12 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public List<SubscriptionsDTO> getGroupsSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, public List<SubscriptionsDTO> getGroupsSubscriptionDetailsByUUID(
int limit) throws ApplicationManagementException { String uuid, String subscriptionStatus, PaginationRequest request, int offset, int limit)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); boolean unsubscribe = subscriptionStatus.equals("unsubscribed");
String groupName;
String status;
try { try {
ConnectionManagerUtil.openDBConnection(); ConnectionManagerUtil.openDBConnection();
@ -1750,8 +1750,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error(msg); log.error(msg);
throw new NotFoundException(msg); throw new NotFoundException(msg);
} }
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(uuid, tenantId);
int appReleaseId = applicationReleaseDTO.getId(); int appReleaseId = applicationReleaseDTO.getId();
List<SubscriptionsDTO> groupDetailsWithDevices = new ArrayList<>(); List<SubscriptionsDTO> groupDetailsWithDevices = new ArrayList<>();
List<GroupSubscriptionDTO> groupDetails = List<GroupSubscriptionDTO> groupDetails =
@ -1763,11 +1763,18 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
GroupManagementProviderService groupManagementProviderService = HelperUtil.getGroupManagementProviderService(); GroupManagementProviderService groupManagementProviderService = HelperUtil.getGroupManagementProviderService();
for (GroupSubscriptionDTO groupDetail : groupDetails) { for (GroupSubscriptionDTO groupDetail : groupDetails) {
groupName = groupDetail.getGroupName();
if (StringUtils.isNotBlank(request.getGroupName()) && !request.getGroupName().equals(groupDetail.getGroupName())) {
continue;
}
String groupName = StringUtils.isNotBlank(request.getGroupName()) ? request.getGroupName() : groupDetail.getGroupName();
// Retrieve group details and device IDs for the group using the service layer // Retrieve group details and device IDs for the group using the service layer
GroupDetailsDTO groupDetailWithDevices = GroupDetailsDTO groupDetailWithDevices =
groupManagementProviderService.getGroupDetailsWithDevices(groupName, offset, limit); groupManagementProviderService.getGroupDetailsWithDevices(
groupName, applicationDTO.getDeviceTypeId(), request.getOwner(),
request.getDeviceName(), request.getDeviceStatus(), offset, limit);
SubscriptionsDTO groupDetailDTO = new SubscriptionsDTO(); SubscriptionsDTO groupDetailDTO = new SubscriptionsDTO();
groupDetailDTO.setId(groupDetailWithDevices.getGroupId()); groupDetailDTO.setId(groupDetailWithDevices.getGroupId());
@ -1790,24 +1797,29 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
List<Integer> deviceIds = groupDetailWithDevices.getDeviceIds(); List<Integer> deviceIds = groupDetailWithDevices.getDeviceIds();
Map<String, Integer> statusCounts = new HashMap<>(); Map<String, Integer> statusCounts = new HashMap<>();
statusCounts.put("PENDING", 0);
statusCounts.put("COMPLETED", 0); statusCounts.put("COMPLETED", 0);
statusCounts.put("ERROR", 0); statusCounts.put("ERROR", 0);
statusCounts.put("PENDING", 0);
statusCounts.put("NEW", 0); statusCounts.put("NEW", 0);
statusCounts.put("SUBSCRIBED", 0); statusCounts.put("SUBSCRIBED", 0);
// Get subscribed devices if unsubscribed devices are requested
List<DeviceSubscriptionDTO> subscribedDeviceSubscriptions = new ArrayList<>();
if (unsubscribe) {
subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
appReleaseId, !unsubscribe, tenantId, deviceIds);
}
for (Integer deviceId : deviceIds) { for (Integer deviceId : deviceIds) {
List<DeviceSubscriptionDTO> deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( // Get subscribed devices if unsubscribed devices are requested
groupDetail.getAppReleaseId(), unsubscribe, tenantId, deviceIds); List<DeviceSubscriptionDTO> deviceSubscriptions;
if (unsubscribe) {
deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
appReleaseId, !unsubscribe, tenantId, deviceIds,
request.getActionStatus(), request.getActionType(), request.getActionTriggeredBy(), request.getTabActionStatus());
} else {
deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
groupDetail.getAppReleaseId(), false, tenantId, deviceIds,
request.getActionStatus(), request.getActionType(), request.getActionTriggeredBy(), request.getTabActionStatus());
}
List<DeviceSubscriptionDTO> filteredDeviceSubscriptions = deviceSubscriptions.stream()
.filter(subscription -> StringUtils.isBlank(request.getTabActionStatus()) || subscription.getStatus().equals(request.getTabActionStatus()))
.collect(Collectors.toList());
boolean isNewDevice = true; boolean isNewDevice = true;
for (DeviceSubscriptionDTO subscription : deviceSubscriptions) { for (DeviceSubscriptionDTO subscription : filteredDeviceSubscriptions) {
if (subscription.getDeviceId() == deviceId) { if (subscription.getDeviceId() == deviceId) {
DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData();
deviceDetail.setDeviceId(subscription.getDeviceId()); deviceDetail.setDeviceId(subscription.getDeviceId());
@ -1825,7 +1837,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
deviceDetail.setType(groupDetailWithDevices.getDeviceTypes().get(deviceId)); deviceDetail.setType(groupDetailWithDevices.getDeviceTypes().get(deviceId));
deviceDetail.setDeviceIdentifier(groupDetailWithDevices.getDeviceIdentifiers().get(deviceId)); deviceDetail.setDeviceIdentifier(groupDetailWithDevices.getDeviceIdentifiers().get(deviceId));
status = subscription.getStatus(); String status = subscription.getStatus();
switch (status) { switch (status) {
case "COMPLETED": case "COMPLETED":
installedDevices.add(deviceDetail); installedDevices.add(deviceDetail);
@ -1843,13 +1855,17 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
pendingDevices.add(deviceDetail); pendingDevices.add(deviceDetail);
statusCounts.put("PENDING", statusCounts.get("PENDING") + 1); statusCounts.put("PENDING", statusCounts.get("PENDING") + 1);
break; break;
default:
newDevices.add(deviceDetail);
statusCounts.put("NEW", statusCounts.get("NEW") + 1);
break;
} }
isNewDevice = false; isNewDevice = false;
} }
} }
if (isNewDevice) { if (isNewDevice) {
boolean isSubscribedDevice = false; boolean isSubscribedDevice = false;
for (DeviceSubscriptionDTO subscribedDevice : subscribedDeviceSubscriptions) { for (DeviceSubscriptionDTO subscribedDevice : deviceSubscriptions) {
if (subscribedDevice.getDeviceId() == deviceId) { if (subscribedDevice.getDeviceId() == deviceId) {
DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData();
subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId()); subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId());
@ -1891,17 +1907,38 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage));
} }
CategorizedSubscriptionResult categorizedSubscriptionResult; List<DeviceSubscriptionData> requestedDevices = new ArrayList<>();
if (subscribedDevices.isEmpty()) { if (StringUtils.isNotBlank(request.getTabActionStatus())) {
categorizedSubscriptionResult = switch (request.getTabActionStatus()) {
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); case "COMPLETED":
requestedDevices = installedDevices;
break;
case "PENDING":
requestedDevices = pendingDevices;
break;
case "ERROR":
requestedDevices = errorDevices;
break;
case "NEW":
requestedDevices = newDevices;
break;
case "SUBSCRIBED":
requestedDevices = subscribedDevices;
break;
}
groupDetailDTO.setDevices(new CategorizedSubscriptionResult(requestedDevices, request.getTabActionStatus()));
} else { } else {
categorizedSubscriptionResult = CategorizedSubscriptionResult categorizedSubscriptionResult;
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); if (subscribedDevices.isEmpty()) {
categorizedSubscriptionResult =
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices);
} else {
categorizedSubscriptionResult =
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices);
}
groupDetailDTO.setDevices(categorizedSubscriptionResult);
} }
groupDetailDTO.setDevices(categorizedSubscriptionResult);
groupDetailDTO.setStatusPercentages(statusPercentages); groupDetailDTO.setStatusPercentages(statusPercentages);
groupDetailsWithDevices.add(groupDetailDTO); groupDetailsWithDevices.add(groupDetailDTO);
} }
@ -1924,11 +1961,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public List<SubscriptionsDTO> getUserSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) public List<SubscriptionsDTO> getUserSubscriptionsByUUID(String uuid, String subscriptionStatus,
PaginationRequest request, int offset, int limit)
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); boolean unsubscribe = subscriptionStatus.equals("unsubscribed");
String userName;
String status; String status;
try { try {
@ -1940,8 +1977,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error(msg); log.error(msg);
throw new NotFoundException(msg); throw new NotFoundException(msg);
} }
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(uuid, tenantId);
int appReleaseId = applicationReleaseDTO.getId(); int appReleaseId = applicationReleaseDTO.getId();
List<SubscriptionsDTO> userSubscriptionsWithDevices = new ArrayList<>(); List<SubscriptionsDTO> userSubscriptionsWithDevices = new ArrayList<>();
List<SubscriptionsDTO> userSubscriptions = List<SubscriptionsDTO> userSubscriptions =
@ -1953,11 +1990,17 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService();
for (SubscriptionsDTO userSubscription : userSubscriptions) { for (SubscriptionsDTO userSubscription : userSubscriptions) {
userName = userSubscription.getName();
if (StringUtils.isNotBlank(request.getUserName()) && !request.getUserName().equals(userSubscription.getName())) {
continue;
}
String userName = StringUtils.isNotBlank(request.getUserName()) ? request.getUserName() : userSubscription.getName();
// Retrieve owner details and device IDs for the user using the service layer // Retrieve owner details and device IDs for the user using the service layer
OwnerWithDeviceDTO ownerDetailsWithDevices = OwnerWithDeviceDTO ownerDetailsWithDevices =
deviceManagementProviderService.getOwnersWithDeviceIds(userName); deviceManagementProviderService.getOwnersWithDeviceIds(userName, applicationDTO.getDeviceTypeId(),
request.getOwner(), request.getDeviceName(), request.getDeviceStatus());
SubscriptionsDTO userSubscriptionDTO = new SubscriptionsDTO(); SubscriptionsDTO userSubscriptionDTO = new SubscriptionsDTO();
userSubscriptionDTO.setName(userSubscription.getName()); userSubscriptionDTO.setName(userSubscription.getName());
@ -1988,21 +2031,29 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
List<DeviceSubscriptionDTO> subscribedDeviceSubscriptions = new ArrayList<>(); List<DeviceSubscriptionDTO> subscribedDeviceSubscriptions = new ArrayList<>();
if (unsubscribe) { if (unsubscribe) {
subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
appReleaseId, !unsubscribe, tenantId, deviceIds); appReleaseId, !unsubscribe, tenantId, deviceIds, request.getActionStatus(), request.getActionType(),
request.getActionTriggeredBy(), request.getTabActionStatus());
} }
for (Integer deviceId : deviceIds) { for (Integer deviceId : deviceIds) {
List<DeviceSubscriptionDTO> deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( List<DeviceSubscriptionDTO> deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
userSubscription.getAppReleaseId(), unsubscribe, tenantId, deviceIds); userSubscription.getAppReleaseId(), unsubscribe, tenantId, deviceIds, request.getActionStatus(), request.getActionType(),
request.getActionTriggeredBy(), request.getTabActionStatus());
OwnerWithDeviceDTO ownerWithDeviceByDeviceId =
deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId, request.getOwner(), request.getDeviceName(),
request.getDeviceStatus());
if (ownerWithDeviceByDeviceId == null) {
continue;
}
boolean isNewDevice = true; boolean isNewDevice = true;
for (DeviceSubscriptionDTO subscription : deviceSubscriptions) { for (DeviceSubscriptionDTO subscription : deviceSubscriptions) {
if (subscription.getDeviceId() == deviceId) { if (subscription.getDeviceId() == deviceId) {
DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData();
deviceDetail.setDeviceId(subscription.getDeviceId()); deviceDetail.setDeviceId(subscription.getDeviceId());
deviceDetail.setSubId(subscription.getId()); deviceDetail.setSubId(subscription.getId());
deviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); deviceDetail.setDeviceOwner(ownerWithDeviceByDeviceId.getUserName());
deviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); deviceDetail.setDeviceStatus(ownerWithDeviceByDeviceId.getDeviceStatus());
deviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); deviceDetail.setDeviceName(ownerWithDeviceByDeviceId.getDeviceNames());
deviceDetail.setActionType(subscription.getActionTriggeredFrom()); deviceDetail.setActionType(subscription.getActionTriggeredFrom());
deviceDetail.setStatus(subscription.getStatus()); deviceDetail.setStatus(subscription.getStatus());
deviceDetail.setActionType(subscription.getActionTriggeredFrom()); deviceDetail.setActionType(subscription.getActionTriggeredFrom());
@ -2011,8 +2062,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
deviceDetail.setUnsubscribed(subscription.isUnsubscribed()); deviceDetail.setUnsubscribed(subscription.isUnsubscribed());
deviceDetail.setUnsubscribedBy(subscription.getUnsubscribedBy()); deviceDetail.setUnsubscribedBy(subscription.getUnsubscribedBy());
deviceDetail.setUnsubscribedTimestamp(subscription.getUnsubscribedTimestamp()); deviceDetail.setUnsubscribedTimestamp(subscription.getUnsubscribedTimestamp());
deviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); deviceDetail.setType(ownerWithDeviceByDeviceId.getDeviceTypes());
deviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); deviceDetail.setDeviceIdentifier(ownerWithDeviceByDeviceId.getDeviceIdentifiers());
status = subscription.getStatus(); status = subscription.getStatus();
switch (status) { switch (status) {
@ -2042,16 +2093,16 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
if (subscribedDevice.getDeviceId() == deviceId) { if (subscribedDevice.getDeviceId() == deviceId) {
DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData();
subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId()); subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId());
subscribedDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); subscribedDeviceDetail.setDeviceName(ownerWithDeviceByDeviceId.getDeviceNames());
subscribedDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); subscribedDeviceDetail.setDeviceOwner(ownerWithDeviceByDeviceId.getUserName());
subscribedDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); subscribedDeviceDetail.setDeviceStatus(ownerWithDeviceByDeviceId.getDeviceStatus());
subscribedDeviceDetail.setSubId(subscribedDevice.getId()); subscribedDeviceDetail.setSubId(subscribedDevice.getId());
subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy()); subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy());
subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp()); subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp());
subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom()); subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom());
subscribedDeviceDetail.setStatus(subscribedDevice.getStatus()); subscribedDeviceDetail.setStatus(subscribedDevice.getStatus());
subscribedDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); subscribedDeviceDetail.setType(ownerWithDeviceByDeviceId.getDeviceTypes());
subscribedDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); subscribedDeviceDetail.setDeviceIdentifier(ownerWithDeviceByDeviceId.getDeviceIdentifiers());
subscribedDevices.add(subscribedDeviceDetail); subscribedDevices.add(subscribedDeviceDetail);
statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1); statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1);
isSubscribedDevice = true; isSubscribedDevice = true;
@ -2061,11 +2112,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
if (!isSubscribedDevice) { if (!isSubscribedDevice) {
DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData();
newDeviceDetail.setDeviceId(deviceId); newDeviceDetail.setDeviceId(deviceId);
newDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); newDeviceDetail.setDeviceOwner(ownerWithDeviceByDeviceId.getUserName());
newDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); newDeviceDetail.setDeviceStatus(ownerWithDeviceByDeviceId.getDeviceStatus());
newDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); newDeviceDetail.setDeviceName(ownerWithDeviceByDeviceId.getDeviceNames());
newDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); newDeviceDetail.setType(ownerWithDeviceByDeviceId.getDeviceTypes());
newDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); newDeviceDetail.setDeviceIdentifier(ownerWithDeviceByDeviceId.getDeviceIdentifiers());
newDevices.add(newDeviceDetail); newDevices.add(newDeviceDetail);
statusCounts.put("NEW", statusCounts.get("NEW") + 1); statusCounts.put("NEW", statusCounts.get("NEW") + 1);
} }
@ -2080,20 +2131,42 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage));
} }
CategorizedSubscriptionResult categorizedSubscriptionResult; List<DeviceSubscriptionData> requestedDevices = new ArrayList<>();
if (subscribedDevices.isEmpty()) { if (StringUtils.isNotBlank(request.getTabActionStatus())) {
categorizedSubscriptionResult = switch (request.getTabActionStatus()) {
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); case "COMPLETED":
requestedDevices = installedDevices;
break;
case "PENDING":
requestedDevices = pendingDevices;
break;
case "ERROR":
requestedDevices = errorDevices;
break;
case "NEW":
requestedDevices = newDevices;
break;
case "SUBSCRIBED":
requestedDevices = subscribedDevices;
break;
}
userSubscriptionDTO.setDevices(new CategorizedSubscriptionResult(requestedDevices, request.getTabActionStatus()));
} else { } else {
categorizedSubscriptionResult = CategorizedSubscriptionResult categorizedSubscriptionResult;
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); if (subscribedDevices.isEmpty()) {
} categorizedSubscriptionResult =
userSubscriptionDTO.setDevices(categorizedSubscriptionResult); new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices);
userSubscriptionDTO.setStatusPercentages(statusPercentages); } else {
categorizedSubscriptionResult =
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices,
subscribedDevices);
}
userSubscriptionDTO.setDevices(categorizedSubscriptionResult);
userSubscriptionDTO.setStatusPercentages(statusPercentages);
}
userSubscriptionsWithDevices.add(userSubscriptionDTO); userSubscriptionsWithDevices.add(userSubscriptionDTO);
} }
return userSubscriptionsWithDevices; return userSubscriptionsWithDevices;
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
String msg = "Error occurred while getting user subscriptions for the application release UUID: " + uuid; String msg = "Error occurred while getting user subscriptions for the application release UUID: " + uuid;
@ -2111,7 +2184,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public List<SubscriptionsDTO> getRoleSubscriptionsByUUID(String uuid, String subscriptionStatus, int offset, int limit) public List<SubscriptionsDTO> getRoleSubscriptionsByUUID(String uuid, String subscriptionStatus,
PaginationRequest request, int offset, int limit)
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); boolean unsubscribe = subscriptionStatus.equals("unsubscribed");
@ -2127,8 +2201,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error(msg); log.error(msg);
throw new NotFoundException(msg); throw new NotFoundException(msg);
} }
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(uuid, tenantId);
int appReleaseId = applicationReleaseDTO.getId(); int appReleaseId = applicationReleaseDTO.getId();
List<SubscriptionsDTO> roleSubscriptionsWithDevices = new ArrayList<>(); List<SubscriptionsDTO> roleSubscriptionsWithDevices = new ArrayList<>();
List<SubscriptionsDTO> roleSubscriptions = List<SubscriptionsDTO> roleSubscriptions =
@ -2140,7 +2214,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService();
for (SubscriptionsDTO roleSubscription : roleSubscriptions) { for (SubscriptionsDTO roleSubscription : roleSubscriptions) {
roleName = roleSubscription.getName();
roleName = StringUtils.isNotBlank(request.getRoleName()) ? request.getRoleName() : roleSubscription.getName();
SubscriptionsDTO roleSubscriptionDTO = new SubscriptionsDTO(); SubscriptionsDTO roleSubscriptionDTO = new SubscriptionsDTO();
roleSubscriptionDTO.setName(roleSubscription.getName()); roleSubscriptionDTO.setName(roleSubscription.getName());
@ -2169,7 +2244,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
for (String user : users) { for (String user : users) {
OwnerWithDeviceDTO ownerDetailsWithDevices; OwnerWithDeviceDTO ownerDetailsWithDevices;
try { try {
ownerDetailsWithDevices = deviceManagementProviderService.getOwnersWithDeviceIds(user); ownerDetailsWithDevices = deviceManagementProviderService.getOwnersWithDeviceIds(user, applicationDTO.getDeviceTypeId(),
request.getOwner(), request.getDeviceName(), request.getDeviceStatus());
} catch (DeviceManagementDAOException e) { } catch (DeviceManagementDAOException e) {
throw new ApplicationManagementException("Error retrieving owner details with devices for user: " + user, e); throw new ApplicationManagementException("Error retrieving owner details with devices for user: " + user, e);
} }
@ -2180,13 +2256,20 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
List<DeviceSubscriptionDTO> subscribedDeviceSubscriptions = new ArrayList<>(); List<DeviceSubscriptionDTO> subscribedDeviceSubscriptions = new ArrayList<>();
if (unsubscribe) { if (unsubscribe) {
subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( subscribedDeviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
appReleaseId, !unsubscribe, tenantId, deviceIds); appReleaseId, !unsubscribe, tenantId, deviceIds, request.getActionStatus(), request.getActionType(),
request.getActionTriggeredBy(), request.getTabActionStatus());
}
OwnerWithDeviceDTO ownerWithDeviceByDeviceId =
deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId, request.getOwner(), request.getDeviceName(),
request.getDeviceStatus());
if (ownerWithDeviceByDeviceId == null) {
continue;
} }
List<DeviceSubscriptionDTO> deviceSubscriptions; List<DeviceSubscriptionDTO> deviceSubscriptions;
try { try {
deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds( deviceSubscriptions = subscriptionDAO.getSubscriptionDetailsByDeviceIds(
roleSubscription.getAppReleaseId(), unsubscribe, tenantId, deviceIds); roleSubscription.getAppReleaseId(), unsubscribe, tenantId, deviceIds, request.getActionStatus(),
request.getActionType(), request.getActionTriggeredBy(), request.getTabActionStatus());
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
throw new ApplicationManagementException("Error retrieving device subscriptions", e); throw new ApplicationManagementException("Error retrieving device subscriptions", e);
} }
@ -2196,9 +2279,9 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
if (deviceSubscription.getDeviceId() == deviceId) { if (deviceSubscription.getDeviceId() == deviceId) {
DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData();
deviceDetail.setDeviceId(deviceSubscription.getDeviceId()); deviceDetail.setDeviceId(deviceSubscription.getDeviceId());
deviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); deviceDetail.setDeviceName(ownerWithDeviceByDeviceId.getDeviceNames());
deviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); deviceDetail.setDeviceOwner(ownerWithDeviceByDeviceId.getUserName());
deviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); deviceDetail.setDeviceStatus(ownerWithDeviceByDeviceId.getDeviceStatus());
deviceDetail.setActionType(deviceSubscription.getActionTriggeredFrom()); deviceDetail.setActionType(deviceSubscription.getActionTriggeredFrom());
deviceDetail.setStatus(deviceSubscription.getStatus()); deviceDetail.setStatus(deviceSubscription.getStatus());
deviceDetail.setActionType(deviceSubscription.getActionTriggeredFrom()); deviceDetail.setActionType(deviceSubscription.getActionTriggeredFrom());
@ -2208,8 +2291,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
deviceDetail.setUnsubscribed(deviceSubscription.isUnsubscribed()); deviceDetail.setUnsubscribed(deviceSubscription.isUnsubscribed());
deviceDetail.setUnsubscribedBy(deviceSubscription.getUnsubscribedBy()); deviceDetail.setUnsubscribedBy(deviceSubscription.getUnsubscribedBy());
deviceDetail.setUnsubscribedTimestamp(deviceSubscription.getUnsubscribedTimestamp()); deviceDetail.setUnsubscribedTimestamp(deviceSubscription.getUnsubscribedTimestamp());
deviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); deviceDetail.setType(ownerWithDeviceByDeviceId.getDeviceTypes());
deviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); deviceDetail.setDeviceIdentifier(ownerWithDeviceByDeviceId.getDeviceIdentifiers());
status = deviceSubscription.getStatus(); status = deviceSubscription.getStatus();
switch (status) { switch (status) {
@ -2239,16 +2322,16 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
if (subscribedDevice.getDeviceId() == deviceId) { if (subscribedDevice.getDeviceId() == deviceId) {
DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData subscribedDeviceDetail = new DeviceSubscriptionData();
subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId()); subscribedDeviceDetail.setDeviceId(subscribedDevice.getDeviceId());
subscribedDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); subscribedDeviceDetail.setDeviceName(ownerWithDeviceByDeviceId.getDeviceNames());
subscribedDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); subscribedDeviceDetail.setDeviceOwner(ownerWithDeviceByDeviceId.getUserName());
subscribedDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); subscribedDeviceDetail.setDeviceStatus(ownerWithDeviceByDeviceId.getDeviceStatus());
subscribedDeviceDetail.setSubId(subscribedDevice.getId()); subscribedDeviceDetail.setSubId(subscribedDevice.getId());
subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy()); subscribedDeviceDetail.setActionTriggeredBy(subscribedDevice.getSubscribedBy());
subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp()); subscribedDeviceDetail.setActionTriggeredTimestamp(subscribedDevice.getSubscribedTimestamp());
subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom()); subscribedDeviceDetail.setActionType(subscribedDevice.getActionTriggeredFrom());
subscribedDeviceDetail.setStatus(subscribedDevice.getStatus()); subscribedDeviceDetail.setStatus(subscribedDevice.getStatus());
subscribedDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); subscribedDeviceDetail.setType(ownerWithDeviceByDeviceId.getDeviceTypes());
subscribedDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); subscribedDeviceDetail.setDeviceIdentifier(ownerWithDeviceByDeviceId.getDeviceIdentifiers());
subscribedDevices.add(subscribedDeviceDetail); subscribedDevices.add(subscribedDeviceDetail);
statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1); statusCounts.put("SUBSCRIBED", statusCounts.get("SUBSCRIBED") + 1);
isSubscribedDevice = true; isSubscribedDevice = true;
@ -2258,11 +2341,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
if (!isSubscribedDevice) { if (!isSubscribedDevice) {
DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData newDeviceDetail = new DeviceSubscriptionData();
newDeviceDetail.setDeviceId(deviceId); newDeviceDetail.setDeviceId(deviceId);
newDeviceDetail.setDeviceName(ownerDetailsWithDevices.getDeviceNames()); newDeviceDetail.setDeviceName(ownerWithDeviceByDeviceId.getDeviceNames());
newDeviceDetail.setDeviceOwner(ownerDetailsWithDevices.getUserName()); newDeviceDetail.setDeviceOwner(ownerWithDeviceByDeviceId.getUserName());
newDeviceDetail.setDeviceStatus(ownerDetailsWithDevices.getDeviceStatus()); newDeviceDetail.setDeviceStatus(ownerWithDeviceByDeviceId.getDeviceStatus());
newDeviceDetail.setType(ownerDetailsWithDevices.getDeviceTypes()); newDeviceDetail.setType(ownerWithDeviceByDeviceId.getDeviceTypes());
newDeviceDetail.setDeviceIdentifier(ownerDetailsWithDevices.getDeviceIdentifiers()); newDeviceDetail.setDeviceIdentifier(ownerWithDeviceByDeviceId.getDeviceIdentifiers());
newDevices.add(newDeviceDetail); newDevices.add(newDeviceDetail);
statusCounts.put("NEW", statusCounts.get("NEW") + 1); statusCounts.put("NEW", statusCounts.get("NEW") + 1);
} }
@ -2279,23 +2362,46 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage));
} }
CategorizedSubscriptionResult categorizedSubscriptionResult; List<DeviceSubscriptionData> requestedDevices = new ArrayList<>();
if (subscribedDevices.isEmpty()) { if (StringUtils.isNotBlank(request.getTabActionStatus())) {
categorizedSubscriptionResult = switch (request.getTabActionStatus()) {
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); case "COMPLETED":
requestedDevices = installedDevices;
break;
case "PENDING":
requestedDevices = pendingDevices;
break;
case "ERROR":
requestedDevices = errorDevices;
break;
case "NEW":
requestedDevices = newDevices;
break;
case "SUBSCRIBED":
requestedDevices = subscribedDevices;
break;
}
roleSubscriptionDTO.setDevices(new CategorizedSubscriptionResult(requestedDevices, request.getTabActionStatus()));
} else { } else {
categorizedSubscriptionResult = CategorizedSubscriptionResult categorizedSubscriptionResult;
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); 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);
} }
roleSubscriptionDTO.setDevices(categorizedSubscriptionResult);
roleSubscriptionDTO.setStatusPercentages(statusPercentages);
roleSubscriptionDTO.setDeviceCount(totalDevices);
roleSubscriptionsWithDevices.add(roleSubscriptionDTO); roleSubscriptionsWithDevices.add(roleSubscriptionDTO);
} }
return roleSubscriptionsWithDevices; return roleSubscriptionsWithDevices;
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException | DeviceManagementDAOException e) {
String msg = "Error occurred in retrieving role subscriptions with devices"; String msg = "Error occurred in retrieving role subscriptions with devices";
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
@ -2322,7 +2428,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public DeviceSubscriptionResponseDTO getDeviceSubscriptionsDetailsByUUID(String uuid, String subscriptionStatus, int offset, public DeviceSubscriptionResponseDTO getDeviceSubscriptionsDetailsByUUID(String uuid, String subscriptionStatus, PaginationRequest request, int offset,
int limit) throws ApplicationManagementException { int limit) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
@ -2337,6 +2443,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error(msg); log.error(msg);
throw new NotFoundException(msg); throw new NotFoundException(msg);
} }
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(uuid, tenantId);
int appReleaseId = applicationReleaseDTO.getId(); int appReleaseId = applicationReleaseDTO.getId();
DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService();
@ -2351,7 +2458,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
List<DeviceDetailsDTO> allDevices = List<DeviceDetailsDTO> allDevices =
deviceManagementProviderService.getDevicesByTenantId(tenantId); deviceManagementProviderService.getDevicesByTenantId(tenantId, applicationDTO.getDeviceTypeId(),
request.getOwner(), request.getDeviceStatus());
List<Integer> deviceIds = allDevices.stream() List<Integer> deviceIds = allDevices.stream()
.map(DeviceDetailsDTO::getDeviceId) .map(DeviceDetailsDTO::getDeviceId)
@ -2376,9 +2484,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
.collect(Collectors.toMap(DeviceDetailsDTO::getDeviceId, Function.identity())); .collect(Collectors.toMap(DeviceDetailsDTO::getDeviceId, Function.identity()));
List<DeviceSubscriptionDTO> allSubscriptionsForUnSubscribed = List<DeviceSubscriptionDTO> allSubscriptionsForUnSubscribed =
subscriptionDAO.getSubscriptionDetailsByDeviceIds(appReleaseId, !unsubscribe, tenantId, deviceIds); subscriptionDAO.getSubscriptionDetailsByDeviceIds(appReleaseId, !unsubscribe, tenantId, deviceIds, request.getActionStatus(),
request.getActionType(), request.getActionTriggeredBy(), request.getTabActionStatus());
List<DeviceSubscriptionDTO> allSubscriptionsForSubscribed = List<DeviceSubscriptionDTO> allSubscriptionsForSubscribed =
subscriptionDAO.getSubscriptionDetailsByDeviceIds(appReleaseId, unsubscribe, tenantId, deviceIds); subscriptionDAO.getSubscriptionDetailsByDeviceIds(appReleaseId, unsubscribe, tenantId, deviceIds, request.getActionStatus(),
request.getActionType(), request.getActionTriggeredBy(), request.getTabActionStatus());
Map<Integer, DeviceSubscriptionDTO> allSubscriptionForUnSubscribedMap = allSubscriptionsForUnSubscribed.stream() Map<Integer, DeviceSubscriptionDTO> allSubscriptionForUnSubscribedMap = allSubscriptionsForUnSubscribed.stream()
.collect(Collectors.toMap(DeviceSubscriptionDTO::getDeviceId, Function.identity())); .collect(Collectors.toMap(DeviceSubscriptionDTO::getDeviceId, Function.identity()));
Map<Integer, DeviceSubscriptionDTO> allSubscriptionForSubscribedMap = allSubscriptionsForSubscribed.stream() Map<Integer, DeviceSubscriptionDTO> allSubscriptionForSubscribedMap = allSubscriptionsForSubscribed.stream()
@ -2387,11 +2497,12 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
for (DeviceDetailsDTO device : allDevices) { for (DeviceDetailsDTO device : allDevices) {
Integer deviceId = device.getDeviceId(); Integer deviceId = device.getDeviceId();
OwnerWithDeviceDTO ownerWithDevice = OwnerWithDeviceDTO ownerWithDevice =
deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId); deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId, request.getOwner(), request.getDeviceName(),
if (ownerWithDevice == null) { request.getDeviceStatus());
if (ownerWithDevice == null || (request.getDeviceName() != null && !request.getDeviceName().isEmpty() &&
(ownerWithDevice.getDeviceNames() == null || !ownerWithDevice.getDeviceNames().contains(request.getDeviceName())))) {
continue; continue;
} }
if (deviceSubscriptionMap.containsKey(deviceId)) { if (deviceSubscriptionMap.containsKey(deviceId)) {
DeviceSubscriptionDTO subscription = deviceSubscriptionMap.get(deviceId); DeviceSubscriptionDTO subscription = deviceSubscriptionMap.get(deviceId);
DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData();
@ -2480,14 +2591,35 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage));
} }
CategorizedSubscriptionResult categorizedSubscriptionResult; List<DeviceSubscriptionData> requestedDevices = new ArrayList<>();
if (subscribedDevices.isEmpty()) { if (StringUtils.isNotBlank(request.getTabActionStatus())) {
categorizedSubscriptionResult = switch (request.getTabActionStatus()) {
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); case "COMPLETED":
requestedDevices = installedDevices;
break;
case "PENDING":
requestedDevices = pendingDevices;
break;
case "ERROR":
requestedDevices = errorDevices;
break;
case "NEW":
requestedDevices = newDevices;
break;
case "SUBSCRIBED":
requestedDevices = subscribedDevices;
break;
}
} else { } else {
categorizedSubscriptionResult = requestedDevices.addAll(installedDevices);
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices); requestedDevices.addAll(pendingDevices);
requestedDevices.addAll(errorDevices);
requestedDevices.addAll(newDevices);
requestedDevices.addAll(subscribedDevices);
} }
CategorizedSubscriptionResult categorizedSubscriptionResult =
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices, subscribedDevices);
DeviceSubscriptionResponseDTO deviceSubscriptionResponse = DeviceSubscriptionResponseDTO deviceSubscriptionResponse =
new DeviceSubscriptionResponseDTO(totalDevices, statusPercentages, categorizedSubscriptionResult); new DeviceSubscriptionResponseDTO(totalDevices, statusPercentages, categorizedSubscriptionResult);
@ -2509,8 +2641,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public DeviceSubscriptionResponseDTO getAllSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, int offset, int limit) public DeviceSubscriptionResponseDTO getAllSubscriptionDetailsByUUID(String uuid, String subscriptionStatus, PaginationRequest request,
throws ApplicationManagementException { int offset, int limit) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
boolean unsubscribe = subscriptionStatus.equals("unsubscribed"); boolean unsubscribe = subscriptionStatus.equals("unsubscribed");
@ -2523,10 +2655,12 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error(msg); log.error(msg);
throw new NotFoundException(msg); throw new NotFoundException(msg);
} }
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(uuid, tenantId);
int appReleaseId = applicationReleaseDTO.getId(); int appReleaseId = applicationReleaseDTO.getId();
List<DeviceSubscriptionDTO> allSubscriptions = List<DeviceSubscriptionDTO> allSubscriptions =
subscriptionDAO.getAllSubscriptionsDetails(appReleaseId, unsubscribe, tenantId, offset, limit); subscriptionDAO.getAllSubscriptionsDetails(appReleaseId, unsubscribe, tenantId, request.getActionStatus(),
request.getActionType(), request.getActionTriggeredBy(), offset, limit);
// empty response for no subscriptions // empty response for no subscriptions
if (allSubscriptions.isEmpty()) { if (allSubscriptions.isEmpty()) {
@ -2552,16 +2686,18 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
statusCounts.put("NEW", 0); statusCounts.put("NEW", 0);
List<DeviceDetailsDTO> allDevices = List<DeviceDetailsDTO> allDevices =
deviceManagementProviderService.getDevicesByTenantId(tenantId); deviceManagementProviderService.getDevicesByTenantId(tenantId, applicationDTO.getDeviceTypeId(), request.getOwner(),
request.getDeviceStatus());
for (DeviceDetailsDTO device : allDevices) { for (DeviceDetailsDTO device : allDevices) {
Integer deviceId = device.getDeviceId(); Integer deviceId = device.getDeviceId();
OwnerWithDeviceDTO ownerWithDevice = OwnerWithDeviceDTO ownerWithDevice =
deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId); deviceManagementProviderService.getOwnerWithDeviceByDeviceId(deviceId, request.getOwner(), request.getDeviceName(),
if (ownerWithDevice == null) { request.getDeviceStatus());
if (ownerWithDevice == null || (request.getDeviceName() != null && !request.getDeviceName().isEmpty() &&
(ownerWithDevice.getDeviceNames() == null || !ownerWithDevice.getDeviceNames().contains(request.getDeviceName())))) {
continue; continue;
} }
if (allSubscriptionMap.containsKey(deviceId)) { if (allSubscriptionMap.containsKey(deviceId)) {
DeviceSubscriptionDTO subscription = allSubscriptionMap.get(deviceId); DeviceSubscriptionDTO subscription = allSubscriptionMap.get(deviceId);
DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData(); DeviceSubscriptionData deviceDetail = new DeviceSubscriptionData();
@ -2620,6 +2756,29 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage)); statusPercentages.put(entry.getKey(), Double.valueOf(formattedPercentage));
} }
List<DeviceSubscriptionData> requestedDevices = new ArrayList<>();
if (StringUtils.isNotBlank(request.getTabActionStatus())) {
switch (request.getTabActionStatus()) {
case "COMPLETED":
requestedDevices = installedDevices;
break;
case "PENDING":
requestedDevices = pendingDevices;
break;
case "ERROR":
requestedDevices = errorDevices;
break;
case "NEW":
requestedDevices = newDevices;
break;
}
} else {
requestedDevices.addAll(installedDevices);
requestedDevices.addAll(pendingDevices);
requestedDevices.addAll(errorDevices);
requestedDevices.addAll(newDevices);
}
CategorizedSubscriptionResult categorizedSubscriptionResult = CategorizedSubscriptionResult categorizedSubscriptionResult =
new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices); new CategorizedSubscriptionResult(installedDevices, pendingDevices, errorDevices, newDevices);
DeviceSubscriptionResponseDTO result = DeviceSubscriptionResponseDTO result =
@ -2642,7 +2801,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public List<DeviceOperationDTO> getSubscriptionOperationsByUUIDAndDeviceID(int deviceId, String uuid, int offset, int limit) public List<DeviceOperationDTO> getSubscriptionOperationsByUUIDAndDeviceID(int deviceId, String uuid)
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (uuid == null || uuid.isEmpty()) { if (uuid == null || uuid.isEmpty()) {
@ -2661,7 +2820,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService(); DeviceManagementProviderService deviceManagementProviderService = HelperUtil.getDeviceManagementProviderService();
List<DeviceOperationDTO> deviceSubscriptions = List<DeviceOperationDTO> deviceSubscriptions =
subscriptionDAO.getSubscriptionOperationsByAppReleaseIDAndDeviceID(appReleaseId, deviceId, tenantId, offset, limit); subscriptionDAO.getSubscriptionOperationsByAppReleaseIDAndDeviceID(appReleaseId, deviceId, tenantId);
for (DeviceOperationDTO deviceSubscription : deviceSubscriptions) { for (DeviceOperationDTO deviceSubscription : deviceSubscriptions) {
Integer operationId = deviceSubscription.getOperationId(); Integer operationId = deviceSubscription.getOperationId();
if (operationId != null) { if (operationId != null) {

@ -26,7 +26,6 @@ import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager; import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.*;
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager; import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.core.dao.common.ApplicationManagementDAOFactory; import io.entgra.device.mgt.core.application.mgt.core.dao.common.ApplicationManagementDAOFactory;
import io.entgra.device.mgt.core.application.mgt.core.impl.AppmDataHandlerImpl; import io.entgra.device.mgt.core.application.mgt.core.impl.AppmDataHandlerImpl;
@ -35,11 +34,15 @@ import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateMa
import io.entgra.device.mgt.core.application.mgt.core.task.ScheduledAppSubscriptionTaskManager; import io.entgra.device.mgt.core.application.mgt.core.task.ScheduledAppSubscriptionTaskManager;
import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil; import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext; import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.*; import org.osgi.service.component.annotations.*;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.wso2.carbon.ndatasource.core.DataSourceService; import org.wso2.carbon.ndatasource.core.DataSourceService;
import org.wso2.carbon.ntask.core.service.TaskService; import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
@ -109,7 +112,7 @@ public class ApplicationManagementServiceComponent {
bundleContext.registerService(FileTransferService.class.getName(), fileTransferService, null); bundleContext.registerService(FileTransferService.class.getName(), fileTransferService, null);
ScheduledAppSubscriptionTaskManager taskManager = new ScheduledAppSubscriptionTaskManager(); ScheduledAppSubscriptionTaskManager taskManager = new ScheduledAppSubscriptionTaskManager();
// todo: taskManager.scheduleCleanupTask(); taskManager.scheduleCleanupTask();
log.info("ApplicationManagement core bundle has been successfully initialized"); log.info("ApplicationManagement core bundle has been successfully initialized");
} catch (Throwable e) { } catch (Throwable e) {
@ -200,4 +203,25 @@ public class ApplicationManagementServiceComponent {
} }
DataHolder.getInstance().setTaskService(null); DataHolder.getInstance().setTaskService(null);
} }
@Reference(
name = "io.entgra.device.mgt.core.tenant.manager",
service = io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetTenantManagementAdminService")
protected void setTenantManagementAdminService(TenantManagerAdminService tenantManagerAdminService) {
if (log.isDebugEnabled()) {
log.debug("Setting Tenant management admin Service");
}
DataHolder.getInstance().setTenantManagerAdminService(tenantManagerAdminService);
}
@SuppressWarnings("unused")
protected void unsetTenantManagementAdminService(TenantManagerAdminService tenantManagerAdminService) {
if (log.isDebugEnabled()) {
log.debug("Un setting Tenant management admin service");
}
DataHolder.getInstance().setTenantManagerAdminService(null);
}
} }

@ -25,9 +25,9 @@ import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationMa
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager; import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager; import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.*;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager; import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService;
import org.wso2.carbon.ntask.core.service.TaskService; import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
@ -58,6 +58,7 @@ public class DataHolder {
private TaskService taskService; private TaskService taskService;
private FileTransferService fileTransferService; private FileTransferService fileTransferService;
private TenantManagerAdminService tenantManagerAdminService;
private static final DataHolder applicationMgtDataHolder = new DataHolder(); private static final DataHolder applicationMgtDataHolder = new DataHolder();
@ -164,4 +165,12 @@ public class DataHolder {
public void setFileTransferService(FileTransferService fileTransferService) { public void setFileTransferService(FileTransferService fileTransferService) {
this.fileTransferService = fileTransferService; this.fileTransferService = fileTransferService;
} }
public TenantManagerAdminService getTenantManagerAdminService() {
return tenantManagerAdminService;
}
public void setTenantManagerAdminService(TenantManagerAdminService tenantManagerAdminService) {
this.tenantManagerAdminService = tenantManagerAdminService;
}
} }

@ -180,6 +180,7 @@ public class ApplicationManagementUtil {
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(artifactLinkUrl).download(artifactLinkUrl); fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(artifactLinkUrl).download(artifactLinkUrl);
applicationArtifact.setInstallerName(fileDescriptor.getFullQualifiedName()); applicationArtifact.setInstallerName(fileDescriptor.getFullQualifiedName());
applicationArtifact.setInstallerStream(fileDescriptor.getFile()); applicationArtifact.setInstallerStream(fileDescriptor.getFile());
applicationArtifact.setInstallerPath(fileDescriptor.getAbsolutePath());
} }
if (iconLink != null) { if (iconLink != null) {
@ -187,6 +188,7 @@ public class ApplicationManagementUtil {
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(iconLinkUrl).download(iconLinkUrl); fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(iconLinkUrl).download(iconLinkUrl);
applicationArtifact.setIconName(fileDescriptor.getFullQualifiedName()); applicationArtifact.setIconName(fileDescriptor.getFullQualifiedName());
applicationArtifact.setIconStream(fileDescriptor.getFile()); applicationArtifact.setIconStream(fileDescriptor.getFile());
applicationArtifact.setIconPath(fileDescriptor.getAbsolutePath());
} }
if (bannerLink != null) { if (bannerLink != null) {
@ -194,10 +196,12 @@ public class ApplicationManagementUtil {
fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(bannerLinkUrl).download(bannerLinkUrl); fileDescriptor = FileDownloaderServiceProvider.getFileDownloaderService(bannerLinkUrl).download(bannerLinkUrl);
applicationArtifact.setBannerName(fileDescriptor.getFullQualifiedName()); applicationArtifact.setBannerName(fileDescriptor.getFullQualifiedName());
applicationArtifact.setBannerStream(fileDescriptor.getFile()); applicationArtifact.setBannerStream(fileDescriptor.getFile());
applicationArtifact.setBannerPath(fileDescriptor.getAbsolutePath());
} }
if (screenshotLinks != null) { if (screenshotLinks != null) {
Map<String, InputStream> screenshotData = new TreeMap<>(); Map<String, InputStream> screenshotData = new TreeMap<>();
Map<String, String> screenshotPaths = new TreeMap<>();
// This is to handle cases in which multiple screenshots have the same name // This is to handle cases in which multiple screenshots have the same name
Map<String, Integer> screenshotNameCount = new HashMap<>(); Map<String, Integer> screenshotNameCount = new HashMap<>();
URL screenshotLinkUrl; URL screenshotLinkUrl;
@ -208,6 +212,7 @@ public class ApplicationManagementUtil {
screenshotNameCount.put(screenshotName, screenshotNameCount.getOrDefault(screenshotName, 0) + 1); screenshotNameCount.put(screenshotName, screenshotNameCount.getOrDefault(screenshotName, 0) + 1);
screenshotName = FileUtil.generateDuplicateFileName(screenshotName, screenshotNameCount.get(screenshotName)); screenshotName = FileUtil.generateDuplicateFileName(screenshotName, screenshotNameCount.get(screenshotName));
screenshotData.put(screenshotName, fileDescriptor.getFile()); screenshotData.put(screenshotName, fileDescriptor.getFile());
screenshotPaths.put(screenshotName, fileDescriptor.getAbsolutePath());
} }
applicationArtifact.setScreenshots(screenshotData); applicationArtifact.setScreenshots(screenshotData);
} }

@ -74,6 +74,7 @@ public class Constants {
public static final String IS_USER_ABLE_TO_VIEW_ALL_ROLES = "isUserAbleToViewAllRoles"; public static final String IS_USER_ABLE_TO_VIEW_ALL_ROLES = "isUserAbleToViewAllRoles";
public static final String GOOGLE_PLAY_STORE_URL = "https://play.google.com/store/apps/details?id="; public static final String GOOGLE_PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=";
public static final String APPLE_STORE_URL = "https://itunes.apple.com/country/app/app-name/id"; public static final String APPLE_STORE_URL = "https://itunes.apple.com/country/app/app-name/id";
public static final String MICROSOFT_STORE_URL = "https://apps.microsoft.com/detail/";
public static final String GOOGLE_PLAY_SYNCED_APP = "GooglePlaySyncedApp"; public static final String GOOGLE_PLAY_SYNCED_APP = "GooglePlaySyncedApp";
// Subscription task related constants // Subscription task related constants

@ -23,7 +23,9 @@ import com.google.gson.Gson;
import io.entgra.device.mgt.core.application.mgt.common.ChunkDescriptor; import io.entgra.device.mgt.core.application.mgt.common.ChunkDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor; import io.entgra.device.mgt.core.application.mgt.common.FileDescriptor;
import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry; import io.entgra.device.mgt.core.application.mgt.common.FileMetaEntry;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationStorageManagementException;
import io.entgra.device.mgt.core.application.mgt.core.exception.FileTransferServiceHelperUtilException; import io.entgra.device.mgt.core.application.mgt.core.exception.FileTransferServiceHelperUtilException;
import io.entgra.device.mgt.core.application.mgt.core.internal.DataHolder;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.NotFoundException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.NotFoundException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -175,6 +177,12 @@ public class FileTransferServiceHelperUtil {
} }
String []urlPathSegments = downloadUrl.getPath().split("/"); String []urlPathSegments = downloadUrl.getPath().split("/");
FileDescriptor fileDescriptorResolvedFromRelease = resolve(urlPathSegments);
if (fileDescriptorResolvedFromRelease != null) {
return fileDescriptorResolvedFromRelease;
}
if (urlPathSegments.length < 2) { if (urlPathSegments.length < 2) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("URL patch segments contain less than 2 segments"); log.debug("URL patch segments contain less than 2 segments");
@ -234,4 +242,54 @@ public class FileTransferServiceHelperUtil {
throw new FileTransferServiceHelperUtilException("Error encountered while creating artifact file", e); throw new FileTransferServiceHelperUtilException("Error encountered while creating artifact file", e);
} }
} }
private static FileDescriptor resolve(String []urlSegments) throws FileTransferServiceHelperUtilException {
// check the possibility of url is pointing to a file resides in the default storage path
if (urlSegments.length < 4) {
if (log.isDebugEnabled()) {
log.debug("URL path segments contain less than 4 segments");
}
return null;
}
int tenantId;
try {
tenantId = Integer.parseInt(urlSegments[urlSegments.length - 4]);
} catch (NumberFormatException e) {
if (log.isDebugEnabled()) {
log.debug("URL isn't pointing to a file resides in the default storage path");
}
return null;
}
String fileName = urlSegments[urlSegments.length - 1];
String folderName = urlSegments[urlSegments.length - 2];
String appHash = urlSegments[urlSegments.length - 3];
try {
InputStream fileStream = DataHolder.getInstance().
getApplicationStorageManager().getFileStream(appHash, folderName, fileName, tenantId);
if (fileStream == null) {
if (log.isDebugEnabled()) {
log.debug("Could not found the file " + fileName);
}
return null;
}
String []fileNameSegments = fileName.split("\\.(?=[^.]+$)");
if (fileNameSegments.length < 2) {
throw new FileTransferServiceHelperUtilException("Invalid full qualified name encountered :" + fileName);
}
FileDescriptor fileDescriptor = new FileDescriptor();
fileDescriptor.setFile(fileStream);
fileDescriptor.setFullQualifiedName(fileName);
fileDescriptor.setExtension(fileNameSegments[fileNameSegments.length - 1]);
fileDescriptor.setFileName(fileNameSegments[fileNameSegments.length - 2]);
fileDescriptor.setAbsolutePath(DataHolder.getInstance().
getApplicationStorageManager().getAbsolutePathOfFile(appHash, folderName, fileName, tenantId));
return fileDescriptor;
} catch (ApplicationStorageManagementException e) {
throw new FileTransferServiceHelperUtilException("Error encountered while getting file input stream", e);
}
}
} }

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId> <artifactId>cea-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -23,7 +23,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId> <artifactId>cea-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId> <artifactId>cea-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>cea-mgt</artifactId> <artifactId>cea-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>certificate-mgt</artifactId> <artifactId>certificate-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>certificate-mgt</artifactId> <artifactId>certificate-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>certificate-mgt</artifactId> <artifactId>certificate-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -329,7 +329,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY_APPLIED
DEVICE_ID INT NOT NULL, DEVICE_ID INT NOT NULL,
ENROLMENT_ID INT NOT NULL, ENROLMENT_ID INT NOT NULL,
POLICY_ID INT NOT NULL, POLICY_ID INT NOT NULL,
POLICY_CONTENT BLOB NULL, POLICY_CONTENT TEXT NULL,
TENANT_ID INT NOT NULL, TENANT_ID INT NOT NULL,
APPLIED TINYINT NULL, APPLIED TINYINT NULL,
CREATED_TIME TIMESTAMP NULL, CREATED_TIME TIMESTAMP NULL,

@ -336,7 +336,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY_APPLIED (
DEVICE_ID INT NOT NULL , DEVICE_ID INT NOT NULL ,
ENROLMENT_ID INT(11) NOT NULL, ENROLMENT_ID INT(11) NOT NULL,
POLICY_ID INT NOT NULL , POLICY_ID INT NOT NULL ,
POLICY_CONTENT BLOB NULL , POLICY_CONTENT TEXT NULL ,
TENANT_ID INT NOT NULL, TENANT_ID INT NOT NULL,
APPLIED TINYINT(1) NULL , APPLIED TINYINT(1) NULL ,
CREATED_TIME TIMESTAMP NULL , CREATED_TIME TIMESTAMP NULL ,

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -108,6 +108,46 @@
<groupId>org.wso2.carbon.analytics-common</groupId> <groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId> <artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.orbit.com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.com.google.auth-library-oauth2-http</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.io.opencensus</groupId>
<artifactId>opencensus</artifactId>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-api</artifactId>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-contrib-http-util</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.orbit.io.grpc</groupId>
<artifactId>grpc-context</artifactId>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>failureaccess</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -135,15 +175,30 @@
io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm.* io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm.*
</Export-Package> </Export-Package>
<Import-Package> <Import-Package>
com.google.gson;version="[2.9,3)", com.google.gson,
io.entgra.device.mgt.core.device.mgt.common;version="[5.0,6)", org.osgi.framework.*;version="${imp.package.version.osgi.framework}",
io.entgra.device.mgt.core.device.mgt.common.exceptions;version="[5.0,6)", org.osgi.service.*;version="${imp.package.version.osgi.service}",
io.entgra.device.mgt.core.device.mgt.common.operation.mgt;version="[5.0,6)", org.wso2.carbon.utils.*,
io.entgra.device.mgt.core.device.mgt.common.push.notification;version="[5.0,6)", io.entgra.device.mgt.core.device.mgt.common.operation.mgt,
io.entgra.device.mgt.core.device.mgt.core.service;version="[5.0,6)", io.entgra.device.mgt.core.device.mgt.common.push.notification,
org.apache.commons.logging;version="[1.2,2)", org.apache.commons.logging,
org.osgi.service.*;version="${imp.package.version.osgi.service}" io.entgra.device.mgt.core.device.mgt.common.*,
io.entgra.device.mgt.core.device.mgt.core.service,
io.entgra.device.mgt.core.device.mgt.core.config.*,
io.entgra.device.mgt.core.device.mgt.core.config.push.notification.*,
io.entgra.device.mgt.core.device.mgt.extensions.logger.spi,
io.entgra.device.mgt.core.notification.logger.*,
com.google.auth.oauth2.*
</Import-Package> </Import-Package>
<Embed-Dependency>
google-auth-library-oauth2-http;scope=compile|runtime,
google-http-client;scope=compile|runtime,
grpc-context;scope=compile|runtime,
guava;scope=compile|runtime,
opencensus;scope=compile|runtime,
failureaccess;scope=compile|runtime
</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>

@ -32,7 +32,9 @@ public class FCMBasedPushNotificationProvider implements PushNotificationProvide
@Override @Override
public NotificationStrategy getNotificationStrategy(PushNotificationConfig config) { public NotificationStrategy getNotificationStrategy(PushNotificationConfig config) {
return new FCMNotificationStrategy(config); FCMNotificationStrategy fcmNotificationStrategy = new FCMNotificationStrategy(config);
fcmNotificationStrategy.init();
return fcmNotificationStrategy;
} }
} }

@ -17,9 +17,7 @@
*/ */
package io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm; package io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import io.entgra.device.mgt.core.device.mgt.common.Device; import io.entgra.device.mgt.core.device.mgt.common.Device;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.common.push.notification.NotificationContext; import io.entgra.device.mgt.core.device.mgt.common.push.notification.NotificationContext;
@ -27,6 +25,7 @@ import io.entgra.device.mgt.core.device.mgt.common.push.notification.Notificatio
import io.entgra.device.mgt.core.device.mgt.common.push.notification.PushNotificationConfig; import io.entgra.device.mgt.core.device.mgt.common.push.notification.PushNotificationConfig;
import io.entgra.device.mgt.core.device.mgt.common.push.notification.PushNotificationExecutionFailedException; import io.entgra.device.mgt.core.device.mgt.common.push.notification.PushNotificationExecutionFailedException;
import io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm.internal.FCMDataHolder; import io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm.internal.FCMDataHolder;
import io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm.util.FCMUtil;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -39,14 +38,13 @@ import java.util.List;
public class FCMNotificationStrategy implements NotificationStrategy { public class FCMNotificationStrategy implements NotificationStrategy {
private static final Log log = LogFactory.getLog(FCMNotificationStrategy.class); private static final Log log = LogFactory.getLog(FCMNotificationStrategy.class);
private static final String NOTIFIER_TYPE_FCM = "FCM"; private static final String NOTIFIER_TYPE_FCM = "FCM";
private static final String FCM_TOKEN = "FCM_TOKEN"; private static final String FCM_TOKEN = "FCM_TOKEN";
private static final String FCM_ENDPOINT = "https://fcm.googleapis.com/fcm/send";
private static final String FCM_API_KEY = "fcmAPIKey"; private static final String FCM_API_KEY = "fcmAPIKey";
private static final int TIME_TO_LIVE = 2419199; // 1 second less that 28 days private static final int TIME_TO_LIVE = 2419199; // 1 second less than 28 days
private static final int HTTP_STATUS_CODE_OK = 200; private static final int HTTP_STATUS_CODE_OK = 200;
private final PushNotificationConfig config; private final PushNotificationConfig config;
private static final String FCM_ENDPOINT_KEY = "FCM_SERVER_ENDPOINT";
public FCMNotificationStrategy(PushNotificationConfig config) { public FCMNotificationStrategy(PushNotificationConfig config) {
this.config = config; this.config = config;
@ -64,12 +62,14 @@ public class FCMNotificationStrategy implements NotificationStrategy {
Device device = FCMDataHolder.getInstance().getDeviceManagementProviderService() Device device = FCMDataHolder.getInstance().getDeviceManagementProviderService()
.getDeviceWithTypeProperties(ctx.getDeviceId()); .getDeviceWithTypeProperties(ctx.getDeviceId());
if(device.getProperties() != null && getFCMToken(device.getProperties()) != null) { if(device.getProperties() != null && getFCMToken(device.getProperties()) != null) {
this.sendWakeUpCall(ctx.getOperation().getCode(), device); FCMUtil.getInstance().getDefaultApplication().refresh();
sendWakeUpCall(FCMUtil.getInstance().getDefaultApplication().getAccessToken().getTokenValue(),
getFCMToken(device.getProperties()));
} }
} else { } else {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Not using FCM notifier as notifier type is set to " + config.getType() + log.debug("Not using FCM notifier as notifier type is set to " + config.getType() +
" in Platform Configurations."); " in Platform Configurations.");
} }
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
@ -79,71 +79,75 @@ public class FCMNotificationStrategy implements NotificationStrategy {
} }
} }
@Override
public NotificationContext buildContext() {
return null;
}
@Override
public void undeploy() {
} /**
* Send FCM message to the FCM server to initiate the push notification
* @param accessToken Access token to authenticate with the FCM server
* @param registrationId Registration ID of the device
* @throws IOException If an error occurs while sending the request
* @throws PushNotificationExecutionFailedException If an error occurs while sending the push notification
*/
private void sendWakeUpCall(String accessToken, String registrationId) throws IOException,
PushNotificationExecutionFailedException {
HttpURLConnection conn = null;
String fcmServerEndpoint = FCMUtil.getInstance().getContextMetadataProperties()
.getProperty(FCM_ENDPOINT_KEY);
if(fcmServerEndpoint == null) {
String msg = "Encountered configuration issue. " + FCM_ENDPOINT_KEY + " is not defined";
log.error(msg);
throw new PushNotificationExecutionFailedException(msg);
}
private void sendWakeUpCall(String message, Device device) throws IOException, try {
PushNotificationExecutionFailedException { byte[] bytes = getFCMRequest(registrationId).getBytes();
if (device.getProperties() != null) { URL url = new URL(fcmServerEndpoint);
OutputStream os = null; conn = (HttpURLConnection) url.openConnection();
byte[] bytes = getFCMRequest(message, getFCMToken(device.getProperties())).getBytes(); conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
HttpURLConnection conn = null; conn.setRequestMethod("POST");
try { conn.setDoOutput(true);
conn = (HttpURLConnection) new URL(FCM_ENDPOINT).openConnection();
conn.setRequestProperty("Content-Type", "application/json"); try (OutputStream os = conn.getOutputStream()) {
conn.setRequestProperty("Authorization", "key=" + config.getProperty(FCM_API_KEY));
conn.setRequestMethod("POST");
conn.setDoOutput(true);
os = conn.getOutputStream();
os.write(bytes); os.write(bytes);
} finally {
if (os != null) {
os.close();
}
if (conn != null) {
conn.disconnect();
}
} }
int status = conn.getResponseCode(); int status = conn.getResponseCode();
if (log.isDebugEnabled()) { if (status != 200) {
log.debug("Result code: " + status + ", Message: " + conn.getResponseMessage()); log.error("Response Status: " + status + ", Response Message: " + conn.getResponseMessage());
} }
if (status != HTTP_STATUS_CODE_OK) { } finally {
throw new PushNotificationExecutionFailedException("Push notification sending failed with the HTTP " + if (conn != null) {
"error code '" + status + "'"); conn.disconnect();
} }
} }
} }
private static String getFCMRequest(String message, String registrationId) { /**
JsonObject fcmRequest = new JsonObject(); * Get the FCM request as a JSON string
fcmRequest.addProperty("delay_while_idle", false); * @param registrationId Registration ID of the device
fcmRequest.addProperty("time_to_live", TIME_TO_LIVE); * @return FCM request as a JSON string
fcmRequest.addProperty("priority", "high"); */
private static String getFCMRequest(String registrationId) {
//Add message to FCM request JsonObject messageObject = new JsonObject();
JsonObject data = new JsonObject(); messageObject.addProperty("token", registrationId);
if (message != null && !message.isEmpty()) {
data.addProperty("data", message);
fcmRequest.add("data", data);
}
//Set device reg-id JsonObject fcmRequest = new JsonObject();
JsonArray regIds = new JsonArray(); fcmRequest.add("message", messageObject);
regIds.add(new JsonPrimitive(registrationId));
fcmRequest.add("registration_ids", regIds);
return fcmRequest.toString(); return fcmRequest.toString();
} }
@Override
public NotificationContext buildContext() {
return null;
}
@Override
public void undeploy() {
}
private static String getFCMToken(List<Device.Property> properties) { private static String getFCMToken(List<Device.Property> properties) {
String fcmToken = null; String fcmToken = null;
for (Device.Property property : properties) { for (Device.Property property : properties) {
@ -159,5 +163,4 @@ public class FCMNotificationStrategy implements NotificationStrategy {
public PushNotificationConfig getConfig() { public PushNotificationConfig getConfig() {
return config; return config;
} }
} }

@ -0,0 +1,108 @@
/*
* 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.extensions.push.notification.provider.fcm.util;
import com.google.auth.oauth2.GoogleCredentials;
import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager;
import io.entgra.device.mgt.core.device.mgt.core.config.push.notification.ContextMetadata;
import io.entgra.device.mgt.core.device.mgt.core.config.push.notification.PushNotificationConfiguration;
import io.entgra.device.mgt.core.device.mgt.extensions.push.notification.provider.fcm.FCMNotificationStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.utils.CarbonUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Properties;
public class FCMUtil {
private static final Log log = LogFactory.getLog(FCMUtil.class);
private static volatile FCMUtil instance;
private static GoogleCredentials defaultApplication;
private static final String FCM_SERVICE_ACCOUNT_PATH = CarbonUtils.getCarbonHome() + File.separator +
"repository" + File.separator + "resources" + File.separator + "service-account.json";
private static final String[] FCM_SCOPES = { "https://www.googleapis.com/auth/firebase.messaging" };
private Properties contextMetadataProperties;
private FCMUtil() {
initContextConfigs();
initDefaultOAuthApplication();
}
private void initDefaultOAuthApplication() {
if (defaultApplication == null) {
Path serviceAccountPath = Paths.get(FCM_SERVICE_ACCOUNT_PATH);
try {
defaultApplication = GoogleCredentials.
fromStream(Files.newInputStream(serviceAccountPath)).
createScoped(FCM_SCOPES);
} catch (IOException e) {
String msg = "Fail to initialize default OAuth application for FCM communication";
log.error(msg);
throw new IllegalStateException(msg, e);
}
}
}
/**
* Initialize the context metadata properties from the cdm-config.xml. This file includes the fcm server URL
* to be invoked when sending the wakeup call to the device.
*/
private void initContextConfigs() {
PushNotificationConfiguration pushNotificationConfiguration = DeviceConfigurationManager.getInstance().
getDeviceManagementConfig().getPushNotificationConfiguration();
List<ContextMetadata> contextMetadata = pushNotificationConfiguration.getContextMetadata();
Properties properties = new Properties();
if (contextMetadata != null) {
for (ContextMetadata metadata : contextMetadata) {
properties.setProperty(metadata.getKey(), metadata.getValue());
}
}
contextMetadataProperties = properties;
}
/**
* Get the instance of FCMUtil. FCMUtil is a singleton class which should not be
* instantiating more than once. Instantiating the class requires to read the service account file from
* the filesystem and instantiation of the GoogleCredentials object which are costly operations.
* @return FCMUtil instance
*/
public static FCMUtil getInstance() {
if (instance == null) {
synchronized (FCMUtil.class) {
if (instance == null) {
instance = new FCMUtil();
}
}
}
return instance;
}
public GoogleCredentials getDefaultApplication() {
return defaultApplication;
}
public Properties getContextMetadataProperties() {
return contextMetadataProperties;
}
}

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt-extensions</artifactId> <artifactId>device-mgt-extensions</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -468,5 +468,10 @@
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.tenant.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -916,6 +916,12 @@ public interface PolicyManagementService {
required = false) required = false)
@QueryParam("status") @QueryParam("status")
String status, String status,
@ApiParam(
name = "deviceType",
value = "The device type of the policy that needs filtering.",
required = false)
@QueryParam("deviceType")
String deviceType,
@ApiParam( @ApiParam(
name = "If-Modified-Since", name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time. \n" + value = "Checks if the requested variant was modified, since the specified date-time. \n" +

@ -298,8 +298,13 @@ public interface UserManagementAdminService {
name = "tenantDomain", name = "tenantDomain",
value = "The domain of the tenant to be deleted.", value = "The domain of the tenant to be deleted.",
required = true) required = true)
@PathParam("tenantDomain") @PathParam("tenantDomain")
String tenantDomain); String tenantDomain,
@ApiParam(
name = "deleteAppArtifacts",
value = "Flag to indicate whether to delete application artifacts.",
required = false)
@QueryParam("deleteAppArtifacts")
@DefaultValue("false")
boolean deleteAppArtifacts);
} }

@ -566,22 +566,49 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Path("/type/{deviceType}/id/{deviceId}/rename") @Path("/type/{deviceType}/id/{deviceId}/rename")
public Response renameDevice(Device device, @PathParam("deviceType") String deviceType, public Response renameDevice(Device device, @PathParam("deviceType") String deviceType,
@PathParam("deviceId") String deviceId) { @PathParam("deviceId") String deviceId) {
if (device == null) {
String msg = "Required values are not set to rename device";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
if (StringUtils.isEmpty(device.getName())) {
String msg = "Device name is not set to rename device";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
DeviceManagementProviderService deviceManagementProviderService = DeviceMgtAPIUtils.getDeviceManagementService(); DeviceManagementProviderService deviceManagementProviderService = DeviceMgtAPIUtils.getDeviceManagementService();
try { try {
Device persistedDevice = deviceManagementProviderService.getDevice(new DeviceIdentifier Device updatedDevice = deviceManagementProviderService.updateDeviceName(device, deviceType, deviceId);
(deviceId, deviceType), true); if (updatedDevice != null) {
persistedDevice.setName(device.getName()); boolean notificationResponse = deviceManagementProviderService.sendDeviceNameChangedNotification(updatedDevice);
System.out.println("This is rename device"); if (notificationResponse) {
boolean responseOfmodifyEnrollment = deviceManagementProviderService.modifyEnrollment(persistedDevice); return Response.status(Response.Status.CREATED).entity(updatedDevice).build();
boolean responseOfDeviceNameChanged = deviceManagementProviderService.sendDeviceNameChangedNotification( } else {
persistedDevice); String msg = "Device updated successfully, but failed to send notification.";
boolean response = responseOfmodifyEnrollment && responseOfDeviceNameChanged; log.warn(msg);
return Response.status(Response.Status.CREATED).entity(updatedDevice).header("Warning", msg).build();
return Response.status(Response.Status.CREATED).entity(response).build(); }
} catch (DeviceManagementException e) { } else {
String msg = "Error encountered while updating requested device of type : " + deviceType ; String msg = "Device update failed for device of type : " + deviceType;
log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
} catch (BadRequestException e) {
String msg = "Bad request: " + e.getMessage();
log.error(msg, e); log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (DeviceNotFoundException e) {
String msg = "Device not found: " + e.getMessage();
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (DeviceManagementException e) {
String msg = "Error encountered while updating requested device of type : " + deviceType;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (ConflictException e) {
String msg = "Conflict encountered while updating requested device of type : " + deviceType;
log.error(msg, e);
return Response.status(Response.Status.CONFLICT).entity(msg).build();
} }
} }

@ -499,6 +499,7 @@ public class PolicyManagementServiceImpl implements PolicyManagementService {
@QueryParam("name") String name, @QueryParam("name") String name,
@QueryParam("type") String type, @QueryParam("type") String type,
@QueryParam("status") String status, @QueryParam("status") String status,
@QueryParam("deviceType") String deviceType,
@HeaderParam("If-Modified-Since") String ifModifiedSince, @HeaderParam("If-Modified-Since") String ifModifiedSince,
@QueryParam("offset") int offset, @QueryParam("offset") int offset,
@QueryParam("limit") int limit) { @QueryParam("limit") int limit) {
@ -516,6 +517,9 @@ public class PolicyManagementServiceImpl implements PolicyManagementService {
if (status != null){ if (status != null){
request.setStatus(status); request.setStatus(status);
} }
if (deviceType != null) {
request.setDeviceType(deviceType);
}
try { try {
PolicyAdministratorPoint policyAdministratorPoint = policyManagementService.getPAP(); PolicyAdministratorPoint policyAdministratorPoint = policyManagementService.getPAP();
policies = policyAdministratorPoint.getPolicyList(request); policies = policyAdministratorPoint.getPolicyList(request);

@ -19,6 +19,7 @@ package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.admin;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.tenant.mgt.common.exception.TenantMgtException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier;
@ -29,9 +30,6 @@ import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.CredentialManagementR
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.stratos.common.exception.StratosException;
import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService;
import org.wso2.carbon.user.api.UserStoreException;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import javax.ws.rs.*; import javax.ws.rs.*;
@ -91,7 +89,7 @@ public class UserManagementAdminServiceImpl implements UserManagementAdminServic
@DELETE @DELETE
@Path("/domain/{tenantDomain}") @Path("/domain/{tenantDomain}")
@Override @Override
public Response deleteTenantByDomain(@PathParam("tenantDomain") String tenantDomain) { public Response deleteTenantByDomain(@PathParam("tenantDomain") String tenantDomain, @QueryParam("deleteAppArtifacts") boolean deleteAppArtifacts) {
try { try {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
if (tenantId != MultitenantConstants.SUPER_TENANT_ID){ if (tenantId != MultitenantConstants.SUPER_TENANT_ID){
@ -99,15 +97,20 @@ public class UserManagementAdminServiceImpl implements UserManagementAdminServic
log.error(msg); log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build(); return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build();
} else { } else {
if (deleteAppArtifacts) {
DeviceMgtAPIUtils.getApplicationManager().deleteApplicationArtifactsByTenantDomain(tenantDomain);
}
DeviceMgtAPIUtils.getApplicationManager().deleteApplicationDataByTenantDomain(tenantDomain); DeviceMgtAPIUtils.getApplicationManager().deleteApplicationDataByTenantDomain(tenantDomain);
DeviceMgtAPIUtils.getDeviceManagementService().deleteDeviceDataByTenantDomain(tenantDomain); DeviceMgtAPIUtils.getDeviceManagementService().deleteDeviceDataByTenantDomain(tenantDomain);
TenantMgtAdminService tenantMgtAdminService = new TenantMgtAdminService(); DeviceMgtAPIUtils.getTenantManagerAdminService().deleteTenant(tenantDomain);
tenantMgtAdminService.deleteTenant(tenantDomain);
String msg = "Tenant Deletion process has been initiated for tenant:" + tenantDomain; String msg = "Tenant Deletion process has been initiated for tenant:" + tenantDomain;
if (log.isDebugEnabled()) {
log.debug(msg);
}
return Response.status(Response.Status.OK).entity(msg).build(); return Response.status(Response.Status.OK).entity(msg).build();
} }
} catch (StratosException | UserStoreException e) { } catch (TenantMgtException e) {
String msg = "Error deleting tenant: " + tenantDomain; String msg = "Error deleting tenant: " + tenantDomain;
log.error(msg, e); log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();

@ -33,6 +33,7 @@ import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.RequestV
import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService;
import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl;
import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService;
import org.apache.axis2.AxisFault; import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options; import org.apache.axis2.client.Options;
import org.apache.axis2.java.security.SSLProtocolSocketFactory; import org.apache.axis2.java.security.SSLProtocolSocketFactory;
@ -46,7 +47,6 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.analytics.api.AnalyticsDataAPI; import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
import org.wso2.carbon.analytics.stream.persistence.stub.EventStreamPersistenceAdminServiceStub; import org.wso2.carbon.analytics.stream.persistence.stub.EventStreamPersistenceAdminServiceStub;
import org.wso2.carbon.authenticator.stub.AuthenticationAdminStub;
import org.wso2.carbon.base.ServerConfiguration; import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
@ -167,6 +167,7 @@ public class DeviceMgtAPIUtils {
private static volatile ConsumerRESTAPIServices consumerRESTAPIServices; private static volatile ConsumerRESTAPIServices consumerRESTAPIServices;
private static volatile APIManagementProviderService apiManagementProviderService; private static volatile APIManagementProviderService apiManagementProviderService;
private static volatile APIPublisherService apiPublisher; private static volatile APIPublisherService apiPublisher;
private static volatile TenantManagerAdminService tenantManagerAdminService;
static { static {
String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password"); String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password");
@ -1304,4 +1305,21 @@ public class DeviceMgtAPIUtils {
} }
return isPermitted; return isPermitted;
} }
public static TenantManagerAdminService getTenantManagerAdminService(){
if(tenantManagerAdminService == null) {
synchronized (DeviceMgtAPIUtils.class) {
if (tenantManagerAdminService == null) {
tenantManagerAdminService = (TenantManagerAdminService) PrivilegedCarbonContext.getThreadLocalCarbonContext().
getOSGiService(TenantManagerAdminService.class, null);
if (tenantManagerAdminService == null) {
String msg = "Tenant Manager Admin Service is null";
log.error(msg);
throw new IllegalStateException(msg);
}
}
}
}
return tenantManagerAdminService;
}
} }

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -58,6 +58,8 @@ public class MDMAppConstants {
} }
public static final String INSTALL_ENTERPRISE_APPLICATION = "INSTALL_ENTERPRISE_APPLICATION"; public static final String INSTALL_ENTERPRISE_APPLICATION = "INSTALL_ENTERPRISE_APPLICATION";
public static final String UNINSTALL_ENTERPRISE_APPLICATION = "UNINSTALL_ENTERPRISE_APPLICATION"; public static final String UNINSTALL_ENTERPRISE_APPLICATION = "UNINSTALL_ENTERPRISE_APPLICATION";
public static final String INSTALL_STORE_APPLICATION = "INSTALL_STORE_APPLICATION";
public static final String UNINSTALL_STORE_APPLICATION = "UNINSTALL_STORE_APPLICATION";
public static final String INSTALL_WEB_CLIP_APPLICATION = "INSTALL_WEB_CLIP"; public static final String INSTALL_WEB_CLIP_APPLICATION = "INSTALL_WEB_CLIP";
public static final String UNINSTALL_WEB_CLIP_APPLICATION = "UNINSTALL_WEB_CLIP"; public static final String UNINSTALL_WEB_CLIP_APPLICATION = "UNINSTALL_WEB_CLIP";
//App type constants related to window device type //App type constants related to window device type

@ -37,6 +37,14 @@ public class PaginationRequest {
private Date since; private Date since;
private String filter; private String filter;
private String serialNumber; private String serialNumber;
private String groupName;
private String roleName;
private String userName;
private String deviceStatus;
private String tabActionStatus;
private String actionStatus;
private String actionType;
private String actionTriggeredBy;
private Map<String, String> customProperty = new HashMap<>(); private Map<String, String> customProperty = new HashMap<>();
private Map<String, Object> property = new HashMap<>(); private Map<String, Object> property = new HashMap<>();
private List<String> statusList = new ArrayList<>(); private List<String> statusList = new ArrayList<>();
@ -216,4 +224,68 @@ public class PaginationRequest {
+ this.ownership + "' Status '" + this.statusList + "' owner '" + this.owner + "' groupId: " + this.groupId + this.ownership + "' Status '" + this.statusList + "' owner '" + this.owner + "' groupId: " + this.groupId
+ " start index: " + this.startIndex + ", SortColumns: " + this.sortColumn; + " start index: " + this.startIndex + ", SortColumns: " + this.sortColumn;
} }
public String getDeviceStatus() {
return deviceStatus;
}
public void setDeviceStatus(String deviceStatus) {
this.deviceStatus = deviceStatus;
}
public String getActionStatus() {
return actionStatus;
}
public void setActionStatus(String actionStatus) {
this.actionStatus = actionStatus;
}
public String getActionType() {
return actionType;
}
public void setActionType(String actionType) {
this.actionType = actionType;
}
public String getActionTriggeredBy() {
return actionTriggeredBy;
}
public void setActionTriggeredBy(String actionTriggeredBy) {
this.actionTriggeredBy = actionTriggeredBy;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getTabActionStatus() {
return tabActionStatus;
}
public void setTabActionStatus(String tabActionStatus) {
this.tabActionStatus = tabActionStatus;
}
} }

@ -24,6 +24,7 @@ public class PolicyPaginationRequest {
private String name; private String name;
private String type; private String type;
private String status; private String status;
private String deviceType;
public PolicyPaginationRequest(int start, int rowCount) { public PolicyPaginationRequest(int start, int rowCount) {
this.startIndex = start; this.startIndex = start;
@ -70,6 +71,14 @@ public class PolicyPaginationRequest {
this.status = status; this.status = status;
} }
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
@Override @Override
public String toString() { public String toString() {
return "Group Name '" + this.name + "' num of rows: " + this.rowCount + " start index: " + this.startIndex; return "Group Name '" + this.name + "' num of rows: " + this.rowCount + " start index: " + this.startIndex;

@ -0,0 +1,49 @@
/*
* 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.io.Serializable;
public class AppStoreApplication implements Serializable {
private String type;
private String packageIdentifier;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPackageIdentifier() {
return packageIdentifier;
}
public void setPackageIdentifier(String packageIdentifier) {
this.packageIdentifier = packageIdentifier;
}
public String toJSON() {
Gson gson = new Gson();
return gson.toJson(this);
}
}

@ -0,0 +1,32 @@
/*
* 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.exceptions;
public class ConflictException extends Exception {
private static final long serialVersionUID = -4998775497944307646L;
public ConflictException(String message) {
super(message);
}
public ConflictException(String message, Throwable cause) {
super(message, cause);
}
}

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -23,8 +23,15 @@ import io.entgra.device.mgt.core.device.mgt.core.common.exception.StorageManagem
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import java.io.*; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths;
/** /**
* This is a util class that handles Storage Management related tasks. * This is a util class that handles Storage Management related tasks.
@ -81,13 +88,14 @@ public class StorageManagementUtil {
* @param path Path the file need to be saved in. * @param path Path the file need to be saved in.
*/ */
public static void saveFile(InputStream inputStream, String path) throws IOException { public static void saveFile(InputStream inputStream, String path) throws IOException {
try (OutputStream outStream = new FileOutputStream(new File(path))) { try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get(path)));
byte[] buffer = new byte[inputStream.available()]; BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
if (inputStream.read(buffer) != -1) { byte []buffer = new byte[8192];
outStream.write(buffer); int n;
while ((n = bufferedInputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, n);
} }
} finally { bufferedOutputStream.flush();
inputStream.close();
} }
} }

@ -0,0 +1,47 @@
/*
* 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.config.push.notification;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
@XmlRootElement(name = "ContextMetadata")
public class ContextMetadata {
private String key;
private String value;
@XmlAttribute(name = "key")
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
@XmlValue
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

@ -33,6 +33,7 @@ public class PushNotificationConfiguration {
private int schedulerTaskInitialDelay; private int schedulerTaskInitialDelay;
private boolean schedulerTaskEnabled; private boolean schedulerTaskEnabled;
private List<String> pushNotificationProviders; private List<String> pushNotificationProviders;
private List<ContextMetadata> contextMetadata;
@XmlElement(name = "SchedulerBatchSize", required = true) @XmlElement(name = "SchedulerBatchSize", required = true)
public int getSchedulerBatchSize() { public int getSchedulerBatchSize() {
@ -79,4 +80,14 @@ public class PushNotificationConfiguration {
public void setPushNotificationProviders(List<String> pushNotificationProviders) { public void setPushNotificationProviders(List<String> pushNotificationProviders) {
this.pushNotificationProviders = pushNotificationProviders; this.pushNotificationProviders = pushNotificationProviders;
} }
@XmlElementWrapper(name = "ProviderContextMetadata")
@XmlElement(name = "ContextMetadata", required = true)
public List<ContextMetadata> getContextMetadata() {
return contextMetadata;
}
public void setContextMetadata(List<ContextMetadata> contextMetadata) {
this.contextMetadata = contextMetadata;
}
} }

@ -100,29 +100,42 @@ public interface EnrollmentDAO {
* Retrieves owners and the list of device IDs related to an owner. * Retrieves owners and the list of device IDs related to an owner.
* *
* @param owner the owner whose device IDs need to be retrieved * @param owner the owner whose device IDs need to be retrieved
* @param allowingDeviceStatuses statuses of devices need to be retrieved
* @param tenantId the ID of the tenant * @param tenantId the ID of the tenant
* @param deviceOwner owner of the device
* @param deviceName name of the device
* @param deviceStatus status of the device
* @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user
* @throws DeviceManagementDAOException if an error occurs while fetching the data * @throws DeviceManagementDAOException if an error occurs while fetching the data
*/ */
OwnerWithDeviceDTO getOwnersWithDevices(String owner, int tenantId) throws DeviceManagementDAOException; OwnerWithDeviceDTO getOwnersWithDevices(String owner, List<String> allowingDeviceStatuses, int tenantId, int deviceTypeId,
String deviceOwner, String deviceName, String deviceStatus) throws DeviceManagementDAOException;
/** /**
* Retrieves a list of device IDs with owners and device status. * 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 deviceId the deviceId of the device which user need to be retrieved
* @param tenantId the ID of the tenant * @param tenantId the ID of the tenant
* @param deviceOwner owner of the device
* @param deviceName name of the device
* @param deviceStatus status of the device
* @return {@link OwnerWithDeviceDTO} which contains a list of devices * @return {@link OwnerWithDeviceDTO} which contains a list of devices
* @throws DeviceManagementDAOException if an error occurs while fetching the data * @throws DeviceManagementDAOException if an error occurs while fetching the data
*/ */
OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, int tenantId) OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, int tenantId, String deviceOwner, String deviceName, String deviceStatus)
throws DeviceManagementDAOException; throws DeviceManagementDAOException;
/** /**
* Retrieves owners and the list of device IDs with device status. * Retrieves owners and the list of device IDs with device status.
* *
* @param tenantId the ID of the tenant * @param tenantId the ID of the tenant
* @param allowingDeviceStatuses the allowed device statuses of devices
* @param deviceTypeId the device type id
* @param deviceOwner owner of the device
* @param deviceStatus status of the device
* @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user
* @throws DeviceManagementDAOException if an error occurs while fetching the data * @throws DeviceManagementDAOException if an error occurs while fetching the data
*/ */
List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId) throws DeviceManagementDAOException; List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId, List<String> allowingDeviceStatuses, int deviceTypeId, String deviceOwner,
String deviceStatus) throws DeviceManagementDAOException;
} }

@ -473,13 +473,19 @@ public interface GroupDAO {
* Get group details and list of device IDs related to the group. * Get group details and list of device IDs related to the group.
* *
* @param groupName Group name * @param groupName Group name
* @param allowingDeviceStatuses the statuses of devices
* @param deviceTypeId the device type id
* @param tenantId Tenant ID * @param tenantId Tenant ID
* @param deviceOwner owner of the device
* @param deviceName name of the device
* @param deviceStatus status of the device
* @param offset the offset for the data set * @param offset the offset for the data set
* @param limit the limit 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 * @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 * @throws GroupManagementDAOException if an error occurs while retrieving the group details and devices
*/ */
GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int tenantId, int offset, int limit) GroupDetailsDTO getGroupDetailsWithDevices(String groupName, List<String> allowingDeviceStatuses, int deviceTypeId,
int tenantId, String deviceOwner, String deviceName, String deviceStatus, int offset, int limit)
throws GroupManagementDAOException; throws GroupManagementDAOException;
} }

@ -982,7 +982,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
+ "e.TENANT_ID = ? AND " + "e.TENANT_ID = ? AND "
+ "LOWER(e.OWNER) = LOWER(?) AND " + "LOWER(e.OWNER) = LOWER(?) AND "
+ "e.STATUS IN (", + "e.STATUS IN (",
")) e1 ORDER BY e1.DATE_OF_LAST_UPDATE DESC"); ")) e1 WHERE d.ID = e1.DEVICE_ID ORDER BY e1.DATE_OF_LAST_UPDATE DESC");
deviceStatuses.stream().map(ignored -> "?").forEach(joiner::add); deviceStatuses.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString(); String query = joiner.toString();

@ -563,30 +563,73 @@ public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO {
} }
@Override @Override
public OwnerWithDeviceDTO getOwnersWithDevices(String owner, int tenantId) public OwnerWithDeviceDTO getOwnersWithDevices(String owner, List<String> allowingDeviceStatuses, int tenantId,
throws DeviceManagementDAOException { int deviceTypeId, String deviceOwner, String deviceName,
String deviceStatus) throws DeviceManagementDAOException {
Connection conn = null; Connection conn = null;
OwnerWithDeviceDTO ownerDetails = new OwnerWithDeviceDTO(); OwnerWithDeviceDTO ownerDetails = new OwnerWithDeviceDTO();
List<Integer> deviceIds = new ArrayList<>(); List<Integer> deviceIds = new ArrayList<>();
int deviceCount = 0; 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 " + StringBuilder deviceFilters = new StringBuilder();
for (int i = 0; i < allowingDeviceStatuses.size(); i++) {
deviceFilters.append("?");
if (i < allowingDeviceStatuses.size() - 1) {
deviceFilters.append(",");
}
}
StringBuilder sql = new StringBuilder(
"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 " + "FROM DM_ENROLMENT e " +
"JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " + "JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " +
"WHERE e.OWNER = ? AND e.TENANT_ID = ?"; "WHERE e.OWNER = ? AND e.TENANT_ID = ? AND d.DEVICE_TYPE_ID = ? AND e.STATUS IN (" + deviceFilters + ")");
if (deviceOwner != null && !deviceOwner.isEmpty()) {
sql.append(" AND e.OWNER LIKE ?");
}
if (deviceName != null && !deviceName.isEmpty()) {
sql.append(" AND d.NAME LIKE ?");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
sql.append(" AND e.STATUS = ?");
}
try { try {
conn = this.getConnection(); conn = this.getConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
stmt.setString(1, owner); int index = 1;
stmt.setInt(2, tenantId); stmt.setString(index++, owner);
stmt.setInt(index++, tenantId);
stmt.setInt(index++, deviceTypeId);
for (String status : allowingDeviceStatuses) {
stmt.setString(index++, status);
}
if (deviceOwner != null && !deviceOwner.isEmpty()) {
stmt.setString(index++, "%" + deviceOwner + "%");
}
if (deviceName != null && !deviceName.isEmpty()) {
stmt.setString(index++, "%" + deviceName + "%");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
stmt.setString(index++, deviceStatus);
}
try (ResultSet rs = stmt.executeQuery()) { try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) { while (rs.next()) {
if (ownerDetails.getUserName() == null) { if (ownerDetails.getUserName() == null) {
ownerDetails.setUserName(rs.getString("OWNER")); ownerDetails.setUserName(rs.getString("OWNER"));
ownerDetails.setDeviceStatus(rs.getString("DEVICE_STATUS"));
ownerDetails.setDeviceNames(rs.getString("DEVICE_NAME"));
} }
ownerDetails.setDeviceStatus(rs.getString("DEVICE_STATUS"));
ownerDetails.setDeviceNames(rs.getString("DEVICE_NAME"));
ownerDetails.setDeviceTypes(rs.getString("DEVICE_TYPE"));
ownerDetails.setDeviceIdentifiers(rs.getString("DEVICE_IDENTIFICATION"));
deviceIds.add(rs.getInt("DEVICE_ID")); deviceIds.add(rs.getInt("DEVICE_ID"));
deviceCount++; deviceCount++;
} }
@ -597,34 +640,61 @@ public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO {
log.error(msg, e); log.error(msg, e);
throw new DeviceManagementDAOException(msg, e); throw new DeviceManagementDAOException(msg, e);
} }
ownerDetails.setDeviceIds(deviceIds); ownerDetails.setDeviceIds(deviceIds);
ownerDetails.setDeviceTypes("DEVICE_TYPE");
ownerDetails.setDeviceIdentifiers("DEVICE_IDENTIFICATION");
ownerDetails.setDeviceCount(deviceCount); ownerDetails.setDeviceCount(deviceCount);
return ownerDetails; return ownerDetails;
} }
@Override @Override
public OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, int tenantId) public OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, int tenantId, String deviceOwner, String deviceName,
throws DeviceManagementDAOException { String deviceStatus) throws DeviceManagementDAOException {
OwnerWithDeviceDTO deviceOwnerWithStatus = new OwnerWithDeviceDTO(); OwnerWithDeviceDTO deviceOwnerWithStatus = new OwnerWithDeviceDTO();
Connection conn = null; 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 " + List<Integer> deviceIds = new ArrayList<>();
StringBuilder sql = new StringBuilder(
"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 " + "FROM DM_ENROLMENT e " +
"JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " + "JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " +
"WHERE e.DEVICE_ID = ? AND e.TENANT_ID = ?"; "WHERE e.DEVICE_ID = ? AND e.TENANT_ID = ?");
if (deviceOwner != null && !deviceOwner.isEmpty()) {
sql.append(" AND e.OWNER LIKE ?");
}
if (deviceName != null && !deviceName.isEmpty()) {
sql.append(" AND d.NAME LIKE ?");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
sql.append(" AND e.STATUS = ?");
}
try { try {
conn = this.getConnection(); conn = this.getConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
stmt.setInt(1, deviceId); int paramIndex = 1;
stmt.setInt(2, tenantId); stmt.setInt(paramIndex++, deviceId);
stmt.setInt(paramIndex++, tenantId);
// Set filter parameters if provided
if (deviceOwner != null && !deviceOwner.isEmpty()) {
stmt.setString(paramIndex++, "%" + deviceOwner + "%");
}
if (deviceName != null && !deviceName.isEmpty()) {
stmt.setString(paramIndex++, "%" + deviceName + "%");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
stmt.setString(paramIndex++, deviceStatus);
}
try (ResultSet rs = stmt.executeQuery()) { try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) { if (rs.next()) {
deviceOwnerWithStatus.setUserName(rs.getString("OWNER")); deviceOwnerWithStatus.setUserName(rs.getString("OWNER"));
deviceOwnerWithStatus.setDeviceStatus(rs.getString("DEVICE_STATUS")); deviceOwnerWithStatus.setDeviceStatus(rs.getString("DEVICE_STATUS"));
List<Integer> deviceIds = new ArrayList<>();
deviceIds.add(rs.getInt("DEVICE_ID")); deviceIds.add(rs.getInt("DEVICE_ID"));
deviceOwnerWithStatus.setDeviceIds(deviceIds); deviceOwnerWithStatus.setDeviceIds(deviceIds);
deviceOwnerWithStatus.setDeviceNames(rs.getString("DEVICE_NAME")); deviceOwnerWithStatus.setDeviceNames(rs.getString("DEVICE_NAME"));
@ -642,18 +712,51 @@ public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO {
} }
@Override @Override
public List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId) public List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId, List<String> allowingDeviceStatuses, int deviceTypeId,
throws DeviceManagementDAOException { String deviceOwner, String deviceStatus) throws DeviceManagementDAOException {
List<DeviceDetailsDTO> devices = new ArrayList<>(); List<DeviceDetailsDTO> devices = new ArrayList<>();
String sql = "SELECT DEVICE_ID, OWNER, STATUS, DEVICE_TYPE, DEVICE_IDENTIFICATION " + if (allowingDeviceStatuses.isEmpty()) {
"FROM DM_ENROLMENT " + return devices;
"WHERE TENANT_ID = ?"; }
StringBuilder deviceFilters = new StringBuilder();
for (int i = 0; i < allowingDeviceStatuses.size(); i++) {
deviceFilters.append("?");
if (i < allowingDeviceStatuses.size() - 1) {
deviceFilters.append(",");
}
}
StringBuilder sql = new StringBuilder("SELECT e.DEVICE_ID, e.OWNER, e.STATUS, e.DEVICE_TYPE, e.DEVICE_IDENTIFICATION " +
"FROM DM_ENROLMENT e " +
"JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " +
"WHERE e.TENANT_ID = ? AND e.STATUS IN (" + deviceFilters.toString() + ") AND d.DEVICE_TYPE_ID = ?");
if (deviceOwner != null && !deviceOwner.isEmpty()) {
sql.append(" AND e.OWNER LIKE ?");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
sql.append(" AND e.STATUS = ?");
}
Connection conn = null; Connection conn = null;
try { try {
conn = this.getConnection(); conn = this.getConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
stmt.setInt(1, tenantId); int index = 1;
stmt.setInt(index++, tenantId);
for (String status : allowingDeviceStatuses) {
stmt.setString(index++, status);
}
stmt.setInt(index++, deviceTypeId);
if (deviceOwner != null && !deviceOwner.isEmpty()) {
stmt.setString(index++, "%" + deviceOwner + "%");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
stmt.setString(index++, deviceStatus);
}
try (ResultSet rs = stmt.executeQuery()) { try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) { while (rs.next()) {

@ -1441,7 +1441,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
} }
@Override @Override
public GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int tenantId, int offset, int limit) public GroupDetailsDTO getGroupDetailsWithDevices(String groupName, List<String> allowedStatuses, int deviceTypeId, int tenantId,
String deviceOwner, String deviceName, String deviceStatus, int offset, int limit)
throws GroupManagementDAOException { throws GroupManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get group details and device IDs for group: " + groupName); log.debug("Request received in DAO Layer to get group details and device IDs for group: " + groupName);
@ -1454,7 +1455,15 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
Map<Integer, String> deviceTypes = new HashMap<>(); Map<Integer, String> deviceTypes = new HashMap<>();
Map<Integer, String> deviceIdentifiers = new HashMap<>(); Map<Integer, String> deviceIdentifiers = new HashMap<>();
String sql = StringBuilder statusPlaceholders = new StringBuilder();
for (int i = 0; i < allowedStatuses.size(); i++) {
statusPlaceholders.append("?");
if (i < allowedStatuses.size() - 1) {
statusPlaceholders.append(",");
}
}
StringBuilder sql = new StringBuilder(
"SELECT " + "SELECT " +
" g.ID AS GROUP_ID, " + " g.ID AS GROUP_ID, " +
" g.GROUP_NAME, " + " g.GROUP_NAME, " +
@ -1473,16 +1482,45 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
"WHERE " + "WHERE " +
" g.GROUP_NAME = ? " + " g.GROUP_NAME = ? " +
" AND g.TENANT_ID = ? " + " AND g.TENANT_ID = ? " +
"LIMIT ? OFFSET ?"; " AND d.DEVICE_TYPE_ID = ? " +
" AND e.STATUS IN (" + statusPlaceholders + ")");
if (deviceOwner != null && !deviceOwner.isEmpty()) {
sql.append(" AND e.OWNER LIKE ?");
}
if (deviceName != null && !deviceName.isEmpty()) {
sql.append(" AND d.NAME LIKE ?");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
sql.append(" AND e.STATUS = ?");
}
sql.append(" LIMIT ? OFFSET ?");
Connection conn = null; Connection conn = null;
try { try {
conn = GroupManagementDAOFactory.getConnection(); conn = GroupManagementDAOFactory.getConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
stmt.setString(1, groupName); int index = 1;
stmt.setInt(2, tenantId); stmt.setString(index++, groupName);
stmt.setInt(3, limit); stmt.setInt(index++, tenantId);
stmt.setInt(4, offset); stmt.setInt(index++, deviceTypeId);
for (String status : allowedStatuses) {
stmt.setString(index++, status);
}
if (deviceOwner != null && !deviceOwner.isEmpty()) {
stmt.setString(index++, "%" + deviceOwner + "%");
}
if (deviceName != null && !deviceName.isEmpty()) {
stmt.setString(index++, "%" + deviceName + "%");
}
if (deviceStatus != null && !deviceStatus.isEmpty()) {
stmt.setString(index++, deviceStatus);
}
stmt.setInt(index++, limit);
stmt.setInt(index++, offset);
try (ResultSet rs = stmt.executeQuery()) { try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -1500,6 +1538,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
deviceIdentifiers.put(deviceId, rs.getString("DEVICE_IDENTIFICATION")); deviceIdentifiers.put(deviceId, rs.getString("DEVICE_IDENTIFICATION"));
} }
} }
}
groupDetails.setDeviceIds(deviceIds); groupDetails.setDeviceIds(deviceIds);
groupDetails.setDeviceCount(deviceIds.size()); groupDetails.setDeviceCount(deviceIds.size());
groupDetails.setDeviceOwners(deviceOwners); groupDetails.setDeviceOwners(deviceOwners);
@ -1508,11 +1547,10 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
groupDetails.setDeviceTypes(deviceTypes); groupDetails.setDeviceTypes(deviceTypes);
groupDetails.setDeviceIdentifiers(deviceIdentifiers); groupDetails.setDeviceIdentifiers(deviceIdentifiers);
return groupDetails; 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);
} }
} 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);
}
} }
} }

@ -19,6 +19,7 @@
package io.entgra.device.mgt.core.device.mgt.core.service; 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.common.app.mgt.Application;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.ConflictException;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; 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.OperationDTO;
import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO;
@ -1073,27 +1074,40 @@ public interface DeviceManagementProviderService {
* Get owner details and device IDs for a given owner and tenant. * Get owner details and device IDs for a given owner and tenant.
* *
* @param owner the name of the owner. * @param owner the name of the owner.
* @param deviceTypeId the device type id]
* @param deviceOwner owner of the device
* @param deviceName name of the device
* @param deviceStatus status of the device
* @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user. * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user.
* @throws DeviceManagementException if an error occurs while fetching owner details. * @throws DeviceManagementException if an error occurs while fetching owner details.
*/ */
OwnerWithDeviceDTO getOwnersWithDeviceIds(String owner) throws DeviceManagementDAOException; OwnerWithDeviceDTO getOwnersWithDeviceIds(String owner, int deviceTypeId, String deviceOwner, String deviceName, String deviceStatus)
throws DeviceManagementDAOException;
/** /**
* Get owner details and device IDs for a given owner and tenant. * Get owner details and device IDs for a given owner and tenant.
* *
* @param deviceId the deviceId of the device. * @param deviceId the deviceId of the device.
* @param deviceOwner owner of the device
* @param deviceName name of the device
* @param deviceStatus status of the device
* @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user. * @return {@link OwnerWithDeviceDTO} which contains a list of devices related to a user.
* @throws DeviceManagementException if an error occurs while fetching owner details. * @throws DeviceManagementException if an error occurs while fetching owner details.
*/ */
OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId) throws DeviceManagementDAOException; OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, String deviceOwner, String deviceName, String deviceStatus)
throws DeviceManagementDAOException;
/** /**
* Get owner details and device IDs for a given owner and tenant. * Get owner details and device IDs for a given owner and tenant.
* @param tenantId the tenant id which devices need to be retried * @param tenantId the tenant id which devices need to be retried
* @param deviceTypeId the device type id
* @param deviceOwner owner of the device
* @param deviceStatus status of the device
* @return {@link DeviceDetailsDTO} which contains devices details. * @return {@link DeviceDetailsDTO} which contains devices details.
* @throws DeviceManagementException if an error occurs while fetching owner details. * @throws DeviceManagementException if an error occurs while fetching owner details.
*/ */
List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId) throws DeviceManagementDAOException; List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId, int deviceTypeId, String deviceOwner, String deviceStatus)
throws DeviceManagementDAOException;
/** /**
* Get operation details by operation code. * Get operation details by operation code.
@ -1117,4 +1131,17 @@ public interface DeviceManagementProviderService {
*/ */
PaginationResult getDevicesNotInGroup(PaginationRequest request, boolean requireDeviceInfo) PaginationResult getDevicesNotInGroup(PaginationRequest request, boolean requireDeviceInfo)
throws DeviceManagementException; throws DeviceManagementException;
/**
* This method is to update devices names
* @param device {@link Device}
* @param deviceType the type of the device.
* @param deviceId ID of the device.
* @return boolean value of the update status.
* @throws DeviceManagementException if any service level or DAO level error occurs.
* @throws DeviceManagementException if service level null device error occurs.
* @throws ConflictException if service level data conflicts occurs.
*/
Device updateDeviceName(Device device, String deviceType, String deviceId)
throws DeviceManagementException, DeviceNotFoundException, ConflictException;
} }

@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.device.mgt.core.service;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.ConflictException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; 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.dao.TenantDAO;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO;
@ -3925,6 +3926,10 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
DeviceCacheManagerImpl.getInstance().removeDeviceFromCache(deviceIdentifier, this.getTenantId()); DeviceCacheManagerImpl.getInstance().removeDeviceFromCache(deviceIdentifier, this.getTenantId());
} }
private void updateDeviceInCache(DeviceIdentifier deviceIdentifier, Device device) {
DeviceCacheManagerImpl.getInstance().updateDeviceInCache(deviceIdentifier, device, this.getTenantId());
}
/*** /***
* This method removes a given list of devices from the cache * This method removes a given list of devices from the cache
* @param deviceList list of DeviceCacheKey objects * @param deviceList list of DeviceCacheKey objects
@ -5357,13 +5362,19 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} }
@Override @Override
public OwnerWithDeviceDTO getOwnersWithDeviceIds(String owner) throws DeviceManagementDAOException { public OwnerWithDeviceDTO getOwnersWithDeviceIds(String owner, int deviceTypeId, String deviceOwner, String deviceName, String deviceStatus)
throws DeviceManagementDAOException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
OwnerWithDeviceDTO ownerWithDeviceDTO; OwnerWithDeviceDTO ownerWithDeviceDTO;
List<String> allowingDeviceStatuses = new ArrayList<>();
allowingDeviceStatuses.add(EnrolmentInfo.Status.ACTIVE.toString());
allowingDeviceStatuses.add(EnrolmentInfo.Status.INACTIVE.toString());
allowingDeviceStatuses.add(EnrolmentInfo.Status.UNREACHABLE.toString());
try { try {
DeviceManagementDAOFactory.openConnection(); DeviceManagementDAOFactory.openConnection();
ownerWithDeviceDTO = this.enrollmentDAO.getOwnersWithDevices(owner, tenantId); ownerWithDeviceDTO = this.enrollmentDAO.getOwnersWithDevices(owner, allowingDeviceStatuses, tenantId, deviceTypeId, deviceOwner, deviceName, deviceStatus);
if (ownerWithDeviceDTO == null) { if (ownerWithDeviceDTO == null) {
String msg = "No data found for owner: " + owner; String msg = "No data found for owner: " + owner;
log.error(msg); log.error(msg);
@ -5387,13 +5398,14 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
@Override @Override
public OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId) throws DeviceManagementDAOException { public OwnerWithDeviceDTO getOwnerWithDeviceByDeviceId(int deviceId, String deviceOwner, String deviceName, String deviceStatus)
throws DeviceManagementDAOException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
OwnerWithDeviceDTO deviceOwnerWithStatus; OwnerWithDeviceDTO deviceOwnerWithStatus;
try { try {
DeviceManagementDAOFactory.openConnection(); DeviceManagementDAOFactory.openConnection();
deviceOwnerWithStatus = enrollmentDAO.getOwnerWithDeviceByDeviceId(deviceId, tenantId); deviceOwnerWithStatus = enrollmentDAO.getOwnerWithDeviceByDeviceId(deviceId, tenantId, deviceOwner, deviceName, deviceStatus);
if (deviceOwnerWithStatus == null) { if (deviceOwnerWithStatus == null) {
throw new DeviceManagementDAOException("No data found for device ID: " + deviceId); throw new DeviceManagementDAOException("No data found for device ID: " + deviceId);
} }
@ -5414,11 +5426,16 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} }
@Override @Override
public List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId) throws DeviceManagementDAOException { public List<DeviceDetailsDTO> getDevicesByTenantId(int tenantId, int deviceTypeId, String deviceOwner, String deviceStatus)
throws DeviceManagementDAOException {
List<DeviceDetailsDTO> devices; List<DeviceDetailsDTO> devices;
List<String> allowingDeviceStatuses = new ArrayList<>();
allowingDeviceStatuses.add(EnrolmentInfo.Status.ACTIVE.toString());
allowingDeviceStatuses.add(EnrolmentInfo.Status.INACTIVE.toString());
allowingDeviceStatuses.add(EnrolmentInfo.Status.UNREACHABLE.toString());
try { try {
DeviceManagementDAOFactory.openConnection(); DeviceManagementDAOFactory.openConnection();
devices = enrollmentDAO.getDevicesByTenantId(tenantId); devices = enrollmentDAO.getDevicesByTenantId(tenantId, allowingDeviceStatuses, deviceTypeId, deviceOwner, deviceStatus);
if (devices == null || devices.isEmpty()) { if (devices == null || devices.isEmpty()) {
String msg = "No devices found for tenant ID: " + tenantId; String msg = "No devices found for tenant ID: " + tenantId;
log.error(msg); log.error(msg);
@ -5511,4 +5528,52 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
paginationResult.setRecordsTotal(count); paginationResult.setRecordsTotal(count);
return paginationResult; return paginationResult;
} }
@Override
public Device updateDeviceName(Device device, String deviceType, String deviceId)
throws DeviceManagementException, DeviceNotFoundException, ConflictException {
Device persistedDevice = this.getDevice(new DeviceIdentifier(deviceId, deviceType), true);
if (persistedDevice == null) {
String msg = "Device not found for the given deviceId and deviceType";
log.error(msg);
throw new DeviceNotFoundException(msg);
}
if (persistedDevice.getName().equals(device.getName())) {
String msg = "Device names are the same.";
log.info(msg);
throw new ConflictException(msg);
}
persistedDevice.setName(device.getName());
if (log.isDebugEnabled()) {
log.debug("Rename Device name of: " + persistedDevice.getId() + " of type '" + persistedDevice.getType() + "'");
}
DeviceManager deviceManager = this.getDeviceManager(persistedDevice.getType());
if (deviceManager == null) {
String msg = "Device Manager associated with the device type '" + persistedDevice.getType() + "' is null. " +
"Therefore, not attempting method 'modifyEnrolment'";
log.error(msg);
throw new DeviceManagementException(msg);
}
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(persistedDevice.getDeviceIdentifier(), persistedDevice.getType());
try {
DeviceManagementDAOFactory.beginTransaction();
int tenantId = this.getTenantId();
deviceDAO.updateDevice(persistedDevice, tenantId);
DeviceManagementDAOFactory.commitTransaction();
this.updateDeviceInCache(deviceIdentifier, persistedDevice);
return persistedDevice;
} catch (DeviceManagementDAOException e) {
DeviceManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while renaming the device '" + persistedDevice.getId() + "'";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (TransactionManagementException e) {
DeviceManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while initiating transaction to rename device: " + persistedDevice.getId();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
}
} }

@ -377,11 +377,16 @@ public interface GroupManagementProviderService {
* Get group details and device IDs for a given group name. * Get group details and device IDs for a given group name.
* *
* @param groupName the name of the group. * @param groupName the name of the group.
* @param deviceTypeId the device type id
* @param deviceOwner owner of the device
* @param deviceName name of the device
* @param deviceStatus status of the device
* @param offset the offset for the data set * @param offset the offset for the data set
* @param limit the limit 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 * @return {@link GroupDetailsDTO} which containing group details and a list of device IDs
* @throws GroupManagementException if an error occurs while fetching group details. * @throws GroupManagementException if an error occurs while fetching group details.
*/ */
GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int offset, int limit) throws GroupManagementException; GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int deviceTypeId, String deviceOwner, String deviceName, String deviceStatus,
int offset, int limit) throws GroupManagementException;
} }

@ -17,6 +17,7 @@
*/ */
package io.entgra.device.mgt.core.device.mgt.core.service; 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.Device;
import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; 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.DeviceManagementConstants;
@ -25,13 +26,12 @@ import io.entgra.device.mgt.core.device.mgt.common.PaginationResult;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceNotFoundException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceNotFoundException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException;
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.*;
import io.entgra.device.mgt.core.device.mgt.core.dao.*;
import io.entgra.device.mgt.core.device.mgt.core.event.config.GroupAssignmentEventOperationExecutor; import io.entgra.device.mgt.core.device.mgt.core.event.config.GroupAssignmentEventOperationExecutor;
import io.entgra.device.mgt.core.device.mgt.core.geo.task.GeoFenceEventOperationManager; import io.entgra.device.mgt.core.device.mgt.core.geo.task.GeoFenceEventOperationManager;
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMgtConstants; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMgtConstants;
import io.entgra.device.mgt.core.device.mgt.core.util.DeviceManagerUtil; import io.entgra.device.mgt.core.device.mgt.core.util.DeviceManagerUtil;
import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo;
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup;
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupConstants; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupConstants;
import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupRoleWrapper; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupRoleWrapper;
@ -59,7 +59,14 @@ import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.user.api.UserStoreManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -1689,17 +1696,22 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
} }
@Override @Override
public GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int offset, int limit) public GroupDetailsDTO getGroupDetailsWithDevices(String groupName, int deviceTypeId, String deviceOwner, String deviceName, String deviceStatus,
throws GroupManagementException { int offset, int limit) throws GroupManagementException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Retrieving group details and device IDs for group: " + groupName); log.debug("Retrieving group details and device IDs for group: " + groupName);
} }
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
GroupDetailsDTO groupDetailsWithDevices; GroupDetailsDTO groupDetailsWithDevices;
List<String> allowingDeviceStatuses = new ArrayList<>();
allowingDeviceStatuses.add(EnrolmentInfo.Status.ACTIVE.toString());
allowingDeviceStatuses.add(EnrolmentInfo.Status.INACTIVE.toString());
allowingDeviceStatuses.add(EnrolmentInfo.Status.UNREACHABLE.toString());
try { try {
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
groupDetailsWithDevices = this.groupDAO.getGroupDetailsWithDevices(groupName, tenantId, offset, limit); groupDetailsWithDevices = this.groupDAO.getGroupDetailsWithDevices(groupName, allowingDeviceStatuses,
deviceTypeId, tenantId, deviceOwner, deviceName, deviceStatus, offset, limit);
} catch (GroupManagementDAOException | SQLException e) { } catch (GroupManagementDAOException | SQLException e) {
String msg = "Error occurred while retrieving group details and device IDs for group: " + groupName; String msg = "Error occurred while retrieving group details and device IDs for group: " + groupName;
log.error(msg, e); log.error(msg, e);

@ -25,6 +25,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import io.entgra.device.mgt.core.device.mgt.common.MDMAppConstants; import io.entgra.device.mgt.core.device.mgt.common.MDMAppConstants;
import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App; import io.entgra.device.mgt.core.device.mgt.common.app.mgt.App;
import io.entgra.device.mgt.core.device.mgt.common.app.mgt.windows.AppStoreApplication;
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.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.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.HostedMSIApplication;
@ -62,64 +63,26 @@ public class MDMWindowsOperationUtil {
switch (application.getType()) { switch (application.getType()) {
case ENTERPRISE: case ENTERPRISE:
operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_ENTERPRISE_APPLICATION);
EnterpriseApplication enterpriseApplication = new EnterpriseApplication(); EnterpriseApplication enterpriseApplication = new EnterpriseApplication();
if (appType.equalsIgnoreCase(MDMAppConstants.WindowsConstants.APPX)) { createEnterpriseAppPayload(appType, metaJsonArray, enterpriseApplication);
HostedAppxApplication hostedAppxApplication = new HostedAppxApplication(); operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_ENTERPRISE_APPLICATION);
List<String> dependencyPackageList = new ArrayList<>();
for (int i = 0; i < metaJsonArray.size(); i++) {
JsonElement metaElement = metaJsonArray.get(i);
JsonObject metaObject = metaElement.getAsJsonObject();
if (MDMAppConstants.WindowsConstants.APPX_PACKAGE_URI.equals(metaObject.get("key").getAsString())) {
hostedAppxApplication.setPackageUri(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_PACKAGE_FAMILY_NAME.equals(metaObject.get("key").getAsString())) {
hostedAppxApplication.setPackageFamilyName(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_DEPENDENCY_PACKAGE_URL.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
dependencyPackageList.add(metaObject.get("value").getAsString().trim());
hostedAppxApplication.setDependencyPackageUri(dependencyPackageList);
}
else if (MDMAppConstants.WindowsConstants.APPX_CERTIFICATE_HASH.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
hostedAppxApplication.setCertificateHash(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_ENCODED_CERT_CONTENT.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
hostedAppxApplication.setEncodedCertificate(metaObject.get("value").getAsString().trim());
}
}
enterpriseApplication.setHostedAppxApplication(hostedAppxApplication);
} else if (appType.equalsIgnoreCase(MDMAppConstants.WindowsConstants.MSI)) {
HostedMSIApplication hostedMSIApplication = new HostedMSIApplication();
for (int i = 0; i < metaJsonArray.size(); i++) {
JsonElement metaElement = metaJsonArray.get(i);
JsonObject metaObject = metaElement.getAsJsonObject();
if (MDMAppConstants.WindowsConstants.MSI_PRODUCT_ID.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setProductId(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.MSI_CONTENT_URI.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setContentUrl(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.MSI_FILE_HASH.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setFileHash(metaObject.get("value").getAsString().trim());
}
}
enterpriseApplication.setHostedMSIApplication(hostedMSIApplication);
}
operation.setPayLoad(enterpriseApplication.toJSON()); operation.setPayLoad(enterpriseApplication.toJSON());
break; break;
case PUBLIC:
AppStoreApplication appStoreApplication = new AppStoreApplication();
appStoreApplication.setType(application.getType().toString());
appStoreApplication.setPackageIdentifier(application.getIdentifier());
operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_STORE_APPLICATION);
operation.setPayLoad(appStoreApplication.toJSON());
break;
case WEB_CLIP: case WEB_CLIP:
operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_WEB_CLIP_APPLICATION);
WebClipApplication webClipApplication = new WebClipApplication(); WebClipApplication webClipApplication = new WebClipApplication();
webClipApplication.setUrl(application.getLocation()); webClipApplication.setUrl(application.getLocation());
webClipApplication.setName(application.getName()); webClipApplication.setName(application.getName());
webClipApplication.setIcon(application.getIconImage()); webClipApplication.setIcon(application.getIconImage());
webClipApplication.setProperties(application.getProperties()); webClipApplication.setProperties(application.getProperties());
webClipApplication.setType(application.getType().toString()); webClipApplication.setType(application.getType().toString());
operation.setCode(MDMAppConstants.WindowsConstants.INSTALL_WEB_CLIP_APPLICATION);
operation.setPayLoad(webClipApplication.toJSON()); operation.setPayLoad(webClipApplication.toJSON());
break; break;
default: default:
@ -148,64 +111,26 @@ public class MDMWindowsOperationUtil {
switch (application.getType()) { switch (application.getType()) {
case ENTERPRISE: case ENTERPRISE:
operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_ENTERPRISE_APPLICATION);
EnterpriseApplication enterpriseApplication = new EnterpriseApplication(); EnterpriseApplication enterpriseApplication = new EnterpriseApplication();
if (appType.equalsIgnoreCase(MDMAppConstants.WindowsConstants.APPX)) { createEnterpriseAppPayload(appType, metaJsonArray, enterpriseApplication);
HostedAppxApplication hostedAppxApplication = new HostedAppxApplication(); operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_ENTERPRISE_APPLICATION);
List<String> dependencyPackageList = new ArrayList<>();
for (int i = 0; i < metaJsonArray.size(); i++) {
JsonElement metaElement = metaJsonArray.get(i);
JsonObject metaObject = metaElement.getAsJsonObject();
if (MDMAppConstants.WindowsConstants.APPX_PACKAGE_URI.equals(metaObject.get("key").getAsString())) {
hostedAppxApplication.setPackageUri(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_PACKAGE_FAMILY_NAME.equals(metaObject.get("key").getAsString())) {
hostedAppxApplication.setPackageFamilyName(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_DEPENDENCY_PACKAGE_URL.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
dependencyPackageList.add(metaObject.get("value").getAsString().trim());
hostedAppxApplication.setDependencyPackageUri(dependencyPackageList);
}
else if (MDMAppConstants.WindowsConstants.APPX_CERTIFICATE_HASH.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
hostedAppxApplication.setCertificateHash(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_ENCODED_CERT_CONTENT.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
hostedAppxApplication.setEncodedCertificate(metaObject.get("value").getAsString().trim());
}
}
enterpriseApplication.setHostedAppxApplication(hostedAppxApplication);
} else if (appType.equalsIgnoreCase(MDMAppConstants.WindowsConstants.MSI)) {
HostedMSIApplication hostedMSIApplication = new HostedMSIApplication();
for (int i = 0; i < metaJsonArray.size(); i++) {
JsonElement metaElement = metaJsonArray.get(i);
JsonObject metaObject = metaElement.getAsJsonObject();
if (MDMAppConstants.WindowsConstants.MSI_PRODUCT_ID.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setProductId(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.MSI_CONTENT_URI.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setContentUrl(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.MSI_FILE_HASH.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setFileHash(metaObject.get("value").getAsString().trim());
}
}
enterpriseApplication.setHostedMSIApplication(hostedMSIApplication);
}
operation.setPayLoad(enterpriseApplication.toJSON()); operation.setPayLoad(enterpriseApplication.toJSON());
break; break;
case PUBLIC:
AppStoreApplication appStoreApplication = new AppStoreApplication();
appStoreApplication.setType(application.getType().toString());
appStoreApplication.setPackageIdentifier(application.getIdentifier());
operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_STORE_APPLICATION);
operation.setPayLoad(appStoreApplication.toJSON());
break;
case WEB_CLIP: case WEB_CLIP:
operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_WEB_CLIP_APPLICATION);
WebClipApplication webClipApplication = new WebClipApplication(); WebClipApplication webClipApplication = new WebClipApplication();
webClipApplication.setUrl(application.getLocation()); webClipApplication.setUrl(application.getLocation());
webClipApplication.setName(application.getName()); webClipApplication.setName(application.getName());
webClipApplication.setIcon(application.getIconImage()); webClipApplication.setIcon(application.getIconImage());
webClipApplication.setProperties(application.getProperties()); webClipApplication.setProperties(application.getProperties());
webClipApplication.setType(application.getType().toString()); webClipApplication.setType(application.getType().toString());
operation.setCode(MDMAppConstants.WindowsConstants.UNINSTALL_WEB_CLIP_APPLICATION);
operation.setPayLoad(webClipApplication.toJSON()); operation.setPayLoad(webClipApplication.toJSON());
default: default:
String msg = "Application type " + application.getType() + " is not supported"; String msg = "Application type " + application.getType() + " is not supported";
@ -216,6 +141,67 @@ public class MDMWindowsOperationUtil {
return operation; return operation;
} }
/**
* Helper method to create enterprise APPX and MSI app payloads for both install and uninstall operations
* @param appType contains whether the app type is APPX or MSI
* @param metaJsonArray JSON array containing metadata of APPX and MSI apps
* @param enterpriseApplication {@link EnterpriseApplication} contains operation payload content that will be sent to the device
*/
private static void createEnterpriseAppPayload(String appType, JsonArray metaJsonArray, EnterpriseApplication enterpriseApplication) {
JsonElement metaElement;
JsonObject metaObject;
if (MDMAppConstants.WindowsConstants.APPX.equalsIgnoreCase(appType)) {
HostedAppxApplication hostedAppxApplication = new HostedAppxApplication();
List<String> dependencyPackageList = new ArrayList<>();
for (int i = 0; i < metaJsonArray.size(); i++) {
metaElement = metaJsonArray.get(i);
metaObject = metaElement.getAsJsonObject();
if (MDMAppConstants.WindowsConstants.APPX_PACKAGE_URI.equals(metaObject.get("key").getAsString())) {
hostedAppxApplication.setPackageUri(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_PACKAGE_FAMILY_NAME.equals(metaObject.get("key").getAsString())) {
hostedAppxApplication.setPackageFamilyName(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_DEPENDENCY_PACKAGE_URL.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
dependencyPackageList.add(metaObject.get("value").getAsString().trim());
hostedAppxApplication.setDependencyPackageUri(dependencyPackageList);
}
else if (MDMAppConstants.WindowsConstants.APPX_CERTIFICATE_HASH.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
hostedAppxApplication.setCertificateHash(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.APPX_ENCODED_CERT_CONTENT.equals(metaObject.get("key").getAsString())
&& metaObject.has("value")) {
hostedAppxApplication.setEncodedCertificate(metaObject.get("value").getAsString().trim());
}
}
enterpriseApplication.setHostedAppxApplication(hostedAppxApplication);
} else if (MDMAppConstants.WindowsConstants.MSI.equalsIgnoreCase(appType)) {
HostedMSIApplication hostedMSIApplication = new HostedMSIApplication();
for (int i = 0; i < metaJsonArray.size(); i++) {
metaElement = metaJsonArray.get(i);
metaObject = metaElement.getAsJsonObject();
if (MDMAppConstants.WindowsConstants.MSI_PRODUCT_ID.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setProductId(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.MSI_CONTENT_URI.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setContentUrl(metaObject.get("value").getAsString().trim());
}
else if (MDMAppConstants.WindowsConstants.MSI_FILE_HASH.equals(metaObject.get("key").getAsString())) {
hostedMSIApplication.setFileHash(metaObject.get("value").getAsString().trim());
}
}
enterpriseApplication.setHostedMSIApplication(hostedMSIApplication);
}
}
/** /**
* Method to get the installer file extension type for windows type apps(either appx or msi) * Method to get the installer file extension type for windows type apps(either appx or msi)
* *
@ -223,8 +209,7 @@ public class MDMWindowsOperationUtil {
* @return string extension of the windows app types(either appx or msi) * @return string extension of the windows app types(either appx or msi)
*/ */
public static String windowsAppType(String installerName) { public static String windowsAppType(String installerName) {
String extension = installerName.substring(installerName.lastIndexOf(".") + 1); return installerName.substring(installerName.lastIndexOf(".") + 1);
return extension;
} }
/** /**
@ -234,8 +219,7 @@ public class MDMWindowsOperationUtil {
* @return the metaData Json String as Json Array * @return the metaData Json String as Json Array
*/ */
public static JsonArray jsonStringToArray(String metaData) { public static JsonArray jsonStringToArray(String metaData) {
JsonArray metaJsonArray = new JsonParser().parse(metaData).getAsJsonArray(); return new JsonParser().parse(metaData).getAsJsonArray();
return metaJsonArray;
} }

@ -384,6 +384,7 @@
<Scope>win:ops:device-info</Scope> <Scope>win:ops:device-info</Scope>
<Scope>win:ops:security-info</Scope> <Scope>win:ops:security-info</Scope>
<Scope>win:ops:firewall-info</Scope> <Scope>win:ops:firewall-info</Scope>
<Scope>win:ops:os-updates-info</Scope>
<Scope>admin:tenant:view</Scope> <Scope>admin:tenant:view</Scope>
<Scope>dm:admin:devices:usage:view</Scope> <Scope>dm:admin:devices:usage:view</Scope>
<Scope>and:ops:clear-app</Scope> <Scope>and:ops:clear-app</Scope>

@ -338,7 +338,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY_APPLIED (
DEVICE_ID INT NOT NULL , DEVICE_ID INT NOT NULL ,
ENROLMENT_ID INT NOT NULL, ENROLMENT_ID INT NOT NULL,
POLICY_ID INT NOT NULL , POLICY_ID INT NOT NULL ,
POLICY_CONTENT BLOB NULL , POLICY_CONTENT TEXT NULL ,
TENANT_ID INT NOT NULL, TENANT_ID INT NOT NULL,
APPLIED TINYINT NULL , APPLIED TINYINT NULL ,
CREATED_TIME TIMESTAMP NULL , CREATED_TIME TIMESTAMP NULL ,

@ -22,7 +22,7 @@
<parent> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -242,7 +242,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY_APPLIED (
DEVICE_ID INT NOT NULL , DEVICE_ID INT NOT NULL ,
ENROLMENT_ID INT NOT NULL, ENROLMENT_ID INT NOT NULL,
POLICY_ID INT NOT NULL , POLICY_ID INT NOT NULL ,
POLICY_CONTENT BLOB NULL , POLICY_CONTENT TEXT NULL ,
TENANT_ID INT NOT NULL, TENANT_ID INT NOT NULL,
APPLIED TINYINT NULL , APPLIED TINYINT NULL ,
CREATED_TIME TIMESTAMP NULL , CREATED_TIME TIMESTAMP NULL ,

@ -23,7 +23,7 @@
<parent> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>heartbeat-management</artifactId> <artifactId>heartbeat-management</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>identity-extensions</artifactId> <artifactId>identity-extensions</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>identity-extensions</artifactId> <artifactId>identity-extensions</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.parent</artifactId> <artifactId>io.entgra.device.mgt.core.parent</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

@ -23,7 +23,7 @@
<parent> <parent>
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>logger</artifactId> <artifactId>logger</artifactId>
<version>5.1.1-SNAPSHOT</version> <version>5.2.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>io.entgra.device.mgt.core.notification.logger</artifactId> <artifactId>io.entgra.device.mgt.core.notification.logger</artifactId>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save