diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java index 3f5c6e34a29..ffe74120bb7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -175,7 +175,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } } - if (!ApplicationType.WEB_CLIP.toString().equals(applicationDTO.getType())) { + if (!ApplicationType.WEB_CLIP.toString().equals(applicationDTO.getType()) && !SubscriptionType.DEVICE + .toString().equals(subType)) { DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); deviceTypeName = deviceType.getName(); //filter devices by device type @@ -334,6 +335,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { ApplicationDTO applicationDTO = getApplicationDTO(applicationUUID); ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); + //todo need to check application release status if it is not in installable state send forbidden exception int applicationReleaseId = applicationReleaseDTO.getId(); if (!ApplicationType.PUBLIC.toString().equals(applicationDTO.getType())) { String msg = "Application type is not public. Hence you can't perform google ent.install operation on " @@ -343,6 +345,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager { throw new BadRequestException(msg); } + List categories = getApplicationCategories(applicationDTO.getId()); + if (!categories.contains("GooglePlaySyncedApp")) { + String msg = "This is not google play store synced application. Hence can't perform enteprise app " + + "installation."; + log.error(msg); + throw new BadRequestException(msg); + } + DeviceManagementProviderService deviceManagementProviderService = HelperUtil .getDeviceManagementProviderService(); @@ -350,9 +360,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager { List subscribers = new ArrayList<>(); List appInstallingDeviceIds; List appReInstallingDeviceIds = new ArrayList<>(); + List deviceIdentifiers = new ArrayList<>(); //todo validate users, groups and roles if (SubscriptionType.DEVICE.toString().equals(subType)) { + DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); for (T param : params) { DeviceIdentifier deviceIdentifier = (DeviceIdentifier) param; if (StringUtils.isEmpty(deviceIdentifier.getId()) || StringUtils @@ -361,6 +373,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager { + " device type. Hence ignoring the device identifier. "); continue; } + if (!deviceType.getName().equals(deviceIdentifier.getType())) { + log.warn("Found a device identifier which is not matched with the supported device type " + + "of the application release which has UUID " + applicationUUID + " Application " + + "supported device type is " + deviceType.getName() + " and the " + + "identifier of which has a different device type is " + deviceIdentifier.getId()); + continue; + } + deviceIdentifiers.add(deviceIdentifier); devices.add(deviceManagementProviderService.getDevice(deviceIdentifier, false)); } } else if (SubscriptionType.USER.toString().equalsIgnoreCase(subType)) { @@ -397,6 +417,28 @@ public class SubscriptionManagerImpl implements SubscriptionManager { appInstallingDeviceIds.remove(deviceSubscription.getKey()); } + /*If subscription type is not device we need to crete device identifiers object list by referring retrieved + list of devices.*/ + if (!SubscriptionType.DEVICE.toString().equalsIgnoreCase(subType)) { + DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); + String deviceTypeName = deviceType.getName(); + //filter devices by device type + devices.removeIf(device -> !deviceTypeName.equals(device.getType())); + devices.forEach(device -> { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(device.getDeviceIdentifier()); + deviceIdentifier.setType(device.getType()); + deviceIdentifiers.add(deviceIdentifier); + }); + } + + //Installing the application + ApplicationPolicyDTO applicationPolicyDTO = new ApplicationPolicyDTO(); + applicationPolicyDTO.setApplicationDTO(applicationDTO); + applicationPolicyDTO.setDeviceIdentifierList(deviceIdentifiers); + applicationPolicyDTO.setAction(SubAction.INSTALL.toString()); + installEnrollmentApplications(applicationPolicyDTO); + updateSubscriptionsForEntInstall(applicationReleaseId, appInstallingDeviceIds, appReInstallingDeviceIds, subscribers, subType); } catch (DeviceManagementException e) { @@ -569,18 +611,6 @@ public class SubscriptionManagerImpl implements SubscriptionManager { entry.getKey(), action); activityList.add(activity); } - } else if (applicationDTO.getType().equals(ApplicationType.PUBLIC.toString())) { - List categories = getApplicationCategories(applicationDTO.getId()); - if (categories.contains("GooglePlaySyncedApp")) { - ApplicationPolicyDTO applicationPolicyDTO = new ApplicationPolicyDTO(); - applicationPolicyDTO.setApplicationDTO(applicationDTO); - applicationPolicyDTO.setDeviceIdentifierList(deviceIdentifiers); - applicationPolicyDTO.setAction(action); - installEnrollmentApplications(applicationPolicyDTO); - } else { - Activity activity = addAppOperationOnDevices(applicationDTO, deviceIdentifiers, deviceType, action); - activityList.add(activity); - } } else { Activity activity = addAppOperationOnDevices(applicationDTO, deviceIdentifiers, deviceType, action); activityList.add(activity); @@ -982,7 +1012,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { String payload = gson.toJson(applicationPolicyDTO); StringRequestEntity requestEntity = new StringRequestEntity(payload, MediaType.APPLICATION_JSON - , Constants.ApplicationInstall.ENCODING);; + , Constants.ApplicationInstall.ENCODING); httpClient = new HttpClient(); request = new PostMethod(requestUrl); request.addRequestHeader(Constants.ApplicationInstall.AUTHORIZATION diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java index 95edf144200..6d60abc4f78 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java @@ -185,6 +185,94 @@ public interface SubscriptionManagementAPI { @QueryParam("timestamp") String timestamp ); + @POST + @Path("/{uuid}/devices/ent-app-install") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Install an application for devices via google enterprise app installing service", + notes = "This will install an application to a given list of devices", + tags = "Subscription Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:subscription:install") + }) + } + ) + @ApiResponses( + value = { + + }) + Response performEntAppInstallationOnDevices( + @ApiParam( + name = "UUID", + value = "The application UUID", + required = true + ) + @PathParam("uuid") String uuid, + @ApiParam( + name = "installationDetails", + value = "The list of device identifiers", + required = true + ) + @Valid List deviceIdentifiers, + @ApiParam( + name = "timestamp", + value = "Timestamp of scheduled ent. install operation" + ) + @QueryParam("timestamp") String timestamp + ); + + @POST + @Path("/{uuid}/{subType}/ent-app-install") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Install an application for subscription type via google enterprise install.", + notes = "This will install an application to a given subscription type and this is bulk app installation.", + tags = "Subscription Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:subscription:install") + }) + } + ) + @ApiResponses( + value = { + + }) + Response performBulkEntAppInstallation( + @ApiParam( + name = "uuid", + value = "The application release UUID", + required = true + ) + @PathParam("uuid") String uuid, + @ApiParam( + name = "subType", + value = "Subscription type of the app installing operation.", + required = true + ) + @PathParam("subType") String subType, + @ApiParam( + name = "subscribers", + value = "Subscriber list of the application release.", + required = true + ) + @Valid List subscribers, + @ApiParam( + name = "timestamp", + value = "Timestamp of scheduled ent app install operation" + ) + @QueryParam("timestamp") String timestamp + ); + @GET @Path("/{uuid}/devices") @Produces(MediaType.APPLICATION_JSON) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java index 62af127d182..8eaae60374f 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java @@ -89,13 +89,13 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ log.error(msg, e); return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); } catch (BadRequestException e) { - String msg = "Found invalid payload for installing application which has UUID: " + uuid - + ". Hence verify the payload"; + String msg = "Found invalid payload for installing application which has UUID: " + uuid + ". Hence verify " + + "the payload"; log.error(msg, e); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } catch (ForbiddenException e) { - String msg = "Application release is not in the installable state. Hence you are not permitted to install " - + "the application."; + String msg = "Application release is not in the installable state. Hence you are not permitted to perform " + + "the action on the application."; log.error(msg, e); return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); } catch (ApplicationManagementException e) { @@ -132,13 +132,13 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ log.error(msg, e); return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); } catch (BadRequestException e) { - String msg = "Found invalid payload for installing application which has UUID: " + uuid - + ". Hence verify the payload"; + String msg = "Found invalid payload for installing application which has UUID: " + uuid + ". Hence verify " + + "the payload"; log.error(msg, e); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } catch (ForbiddenException e) { - String msg = "Application release is not in the installable state. Hence you are not permitted to install " - + "the application."; + String msg = "Application release is not in the installable state. Hence you are not permitted to perform " + + "the action on the application."; log.error(msg, e); return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); } catch (ApplicationManagementException e) { @@ -149,6 +149,91 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ } } + @Override + @POST + @Path("/{uuid}/devices/ent-app-install") + public Response performEntAppInstallationOnDevices( + @PathParam("uuid") String uuid, + @Valid List deviceIdentifiers, + @QueryParam("timestamp") String timestamp) { + try { + if (StringUtils.isEmpty(timestamp)) { + SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); + subscriptionManager + .performEntAppInstall(uuid, deviceIdentifiers, SubscriptionType.DEVICE.toString()); + String msg = "Application release which has UUID " + uuid + " is installed to given valid device " + + "identifiers."; + return Response.status(Response.Status.OK).entity(msg).build(); + } else { + return scheduleApplicationOperationTask(uuid, deviceIdentifiers, SubscriptionType.DEVICE, + SubAction.valueOf(SubAction.INSTALL.toString().toUpperCase()), timestamp); + } + } catch (NotFoundException e) { + String msg = "Couldn't found an application release for UUI: " + uuid + " to perform ent app installation " + + "on subscriber's devices"; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Found invalid payload when performing ent app installation on application which has UUID: " + + uuid + ". Hence verify the payload of the request."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ForbiddenException e) { + String msg = "Application release is not in the installable state. Hence you are not permitted to install " + + "the application."; + log.error(msg, e); + return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = + "Error occurred while performing ent app installation on the application release which has UUID: " + + uuid + " for devices"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @Override + @POST + @Path("/{uuid}/{subType}/ent-app-install") + public Response performBulkEntAppInstallation( + @PathParam("uuid") String uuid, + @PathParam("subType") String subType, + @Valid List subscribers, + @QueryParam("timestamp") String timestamp) { + try { + if (StringUtils.isEmpty(timestamp)) { + SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); + subscriptionManager.performEntAppInstall(uuid, subscribers, subType); + String msg = "Application release which has UUID " + uuid + " is installed to subscriber's valid device" + + " identifiers."; + return Response.status(Response.Status.OK).entity(msg).build(); + } else { + return scheduleApplicationOperationTask(uuid, subscribers, + SubscriptionType.valueOf(subType.toUpperCase()), + SubAction.valueOf(SubAction.INSTALL.toString().toUpperCase()), timestamp); + } + } catch (NotFoundException e) { + String msg = "Couldn't found an application release for UUID: " + uuid + ". Hence, verify the payload"; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Found invalid payload when performing ent app installation on application which has UUID: " + + uuid + ". Hence verify the payload of the request."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ForbiddenException e) { + String msg = "Application release is not in the installable state. Hence you are not permitted to install " + + "the application."; + log.error(msg, e); + return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while performing ent app installation on the application release which has " + + "UUID: " + uuid + " for user devices"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + /** * Schedule the application subscription for the given timestamp * @@ -183,13 +268,13 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ @Consumes("application/json") @Produces("application/json") @Path("/{uuid}/devices") - public Response getAppInstalledDevices(@PathParam("uuid") String uuid, - @DefaultValue("0") - @QueryParam("offset") int offset, - @DefaultValue("5") - @QueryParam("limit") int limit, - @QueryParam("status") String status) { - + public Response getAppInstalledDevices( + @PathParam("uuid") String uuid, + @DefaultValue("0") + @QueryParam("offset") int offset, + @DefaultValue("5") + @QueryParam("limit") int limit, + @QueryParam("status") String status) { try { SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); @@ -228,13 +313,13 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ @Consumes("application/json") @Produces("application/json") @Path("/{uuid}/{subType}") - public Response getAppInstalledCategories(@PathParam("uuid") String uuid, - @PathParam("subType") String subType, - @DefaultValue("0") - @QueryParam("offset") int offset, - @DefaultValue("5") - @QueryParam("limit") int limit) { - + public Response getAppInstalledCategories( + @PathParam("uuid") String uuid, + @PathParam("subType") String subType, + @DefaultValue("0") + @QueryParam("offset") int offset, + @DefaultValue("5") + @QueryParam("limit") int limit) { try { SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager();