diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f22bfc39ca..2530bdcfa7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,3 +25,4 @@ deploy: - mvn $MAVEN_CLI_OPTS deploy -Dmaven.test.skip=true only: - master@entgra/carbon-device-mgt + - kernel-4.6.x@entgra/carbon-device-mgt diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java index a535ffd389..bc2eaabc47 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java @@ -24,8 +24,10 @@ import org.wso2.carbon.device.application.mgt.common.exception.SubscriptionManag import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.app.mgt.App; import java.util.List; +import java.util.Properties; /** * This interface manages all the operations related with ApplicationDTO Subscription. @@ -33,22 +35,22 @@ import java.util.List; public interface SubscriptionManager { /** * Performs bulk subscription operation for a given application and a subscriber list. - * - * @param applicationUUID UUID of the application to subscribe/unsubscribe + * @param applicationUUID UUID of the application to subscribe/unsubscribe * @param params list of subscribers. This list can be of either - * {@link org.wso2.carbon.device.mgt.common.DeviceIdentifier} if {@param subType} is equal + * {@link DeviceIdentifier} if {@param subType} is equal * to DEVICE or * {@link String} if {@param subType} is USER, ROLE or GROUP * @param subType subscription type. E.g. DEVICE, USER, ROLE, GROUP {@see { - * @param action subscription action. E.g. INSTALL/UNINSTALL {@see { - * @param generic type of the method. - * @return {@link ApplicationInstallResponse} - * @throws ApplicationManagementException if error occurs when subscribing to the given application - * @link org.wso2.carbon.device.application.mgt.common.SubscriptionType}} - * @link org.wso2.carbon.device.application.mgt.common.SubAction}} + * @param action subscription action. E.g. INSTALL/UNINSTALL {@see { + * @param generic type of the method. + * @return {@link ApplicationInstallResponse} + * @throws ApplicationManagementException if error occurs when subscribing to the given application + * @link org.wso2.carbon.device.application.mgt.common.SubscriptionType}} + * @link org.wso2.carbon.device.application.mgt.common.SubAction}} + * @param properties */ ApplicationInstallResponse performBulkAppOperation(String applicationUUID, List params, String subType, - String action) throws ApplicationManagementException; + String action, Properties properties) throws ApplicationManagementException; /** * Create an entry related to the scheduled task in the database. @@ -121,7 +123,7 @@ public interface SubscriptionManager { * @throws ApplicationManagementException if error occurred while installing given applications into the given * device */ - void installAppsForDevice(DeviceIdentifier deviceIdentifier, List releaseUUID) + void installAppsForDevice(DeviceIdentifier deviceIdentifier, List apps) throws ApplicationManagementException; /*** @@ -161,4 +163,16 @@ public interface SubscriptionManager { */ PaginationResult getAppSubscriptionDetails(PaginationRequest request, String appUUID, String actionStatus, String action) throws ApplicationManagementException; + + /*** + * This method is responsible to provide application subscription devices data for given application release UUID. + * @param request PaginationRequest object holding the data for pagination + * @param appUUID UUID of the application release. + * @param subType subscription type of the application(eg: GROUP, USER, ...) + * @param subTypeName subscription type name of the application (Name of the group, Name of the user, ...). + * @return {@link PaginationResult} pagination result of the category details. + * @throws {@link ApplicationManagementException} Exception of the application management + */ + PaginationResult getAppInstalledSubscribeDevices(PaginationRequest request, String appUUID, String subType, + String subTypeName) throws ApplicationManagementException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java index ce8780a6a2..3ff0d95945 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java @@ -228,4 +228,16 @@ public interface SubscriptionDAO { throws ApplicationManagementDAOException; int getSubscribedGroupCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of subscribed groups + * + * @param tenantId id of the current tenant + * @param appReleaseId id of the application release.. + * @param subtype application subscribed type. + * @return subscribedDevices - list of app subscribed devices under the subtype. + * @throws {@link ApplicationManagementDAOException} if connections establishment fails. + */ + List getAppSubscribedDevicesForGroups(int appReleaseId, String subtype, int tenantId) + throws ApplicationManagementDAOException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java index c2fd7f240a..4e6c6623f1 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java @@ -1271,4 +1271,45 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc throw new ApplicationManagementDAOException(msg, e); } } + + @Override + public List getAppSubscribedDevicesForGroups(int appReleaseId, String subType, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get already subscribed devices for " + + "given app release id."); + } + // retrieve all device list by action triggered type and app release id + try { + Connection conn = this.getDBConnection(); + List subscribedGroupDevices = new ArrayList<>(); + String sql = "SELECT " + + "AP_DEVICE_SUBSCRIPTION.DM_DEVICE_ID AS DEVICES " + + "FROM AP_DEVICE_SUBSCRIPTION " + + "WHERE " + + "AP_APP_RELEASE_ID = ? AND ACTION_TRIGGERED_FROM=? AND " + + "UNSUBSCRIBED=FALSE AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setString(2, subType.toLowerCase());; + ps.setInt(3, tenantId); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + subscribedGroupDevices.add(rs.getInt("DEVICES")); + } + } + return subscribedGroupDevices; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get already " + + "subscribed groups for given app release id."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting subscribed devices for given " + + "app release id."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } } 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 5aa222ce13..2de1094c1f 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 @@ -121,7 +121,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { @Override public ApplicationInstallResponse performBulkAppOperation(String applicationUUID, List params, - String subType, String action) throws ApplicationManagementException { + String subType, String action, Properties properties) throws ApplicationManagementException { if (log.isDebugEnabled()) { log.debug("Install application release which has UUID " + applicationUUID + " to " + params.size() + " users."); @@ -134,7 +134,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { params); ApplicationInstallResponse applicationInstallResponse = performActionOnDevices( applicationSubscriptionInfo.getAppSupportingDeviceTypeName(), applicationSubscriptionInfo.getDevices(), - applicationDTO, subType, applicationSubscriptionInfo.getSubscribers(), action); + applicationDTO, subType, applicationSubscriptionInfo.getSubscribers(), action, properties); applicationInstallResponse.setErrorDeviceIdentifiers(applicationSubscriptionInfo.getErrorDeviceIdentifiers()); return applicationInstallResponse; @@ -347,7 +347,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } @Override - public void installAppsForDevice(DeviceIdentifier deviceIdentifier, List releaseUUIDs) + public void installAppsForDevice(DeviceIdentifier deviceIdentifier, List apps) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); @@ -370,7 +370,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager { List appInstallingDevices = new ArrayList<>(); - for (String releaseUUID : releaseUUIDs) { + for (App app : apps) { + String releaseUUID = app.getId(); try { ConnectionManagerUtil.openDBConnection(); ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(releaseUUID, tenantId); @@ -409,7 +410,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { if (!appInstallingDevices.isEmpty()) { performBulkAppOperation(releaseUUID, appInstallingDevices, SubscriptionType.DEVICE.toString(), - SubAction.INSTALL.toString()); + SubAction.INSTALL.toString(), app.getProperties()); } } } @@ -621,7 +622,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { * data. */ private ApplicationInstallResponse performActionOnDevices(String deviceType, List devices, - ApplicationDTO applicationDTO, String subType, List subscribers, String action) + ApplicationDTO applicationDTO, String subType, List subscribers, String action, Properties properties) throws ApplicationManagementException { //Get app subscribing info of each device @@ -667,11 +668,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager { } for (Map.Entry> entry : deviceIdentifierMap.entrySet()) { Activity activity = addAppOperationOnDevices(applicationDTO, new ArrayList<>(entry.getValue()), - entry.getKey(), action); + entry.getKey(), action, properties); activityList.add(activity); } } else { - Activity activity = addAppOperationOnDevices(applicationDTO, deviceIdentifiers, deviceType, action); + Activity activity = addAppOperationOnDevices(applicationDTO, deviceIdentifiers, deviceType, action, properties); activityList.add(activity); } @@ -982,13 +983,13 @@ public class SubscriptionManagerImpl implements SubscriptionManager { * @throws ApplicationManagementException if found an invalid device. */ private Activity addAppOperationOnDevices(ApplicationDTO applicationDTO, - List deviceIdentifierList, String deviceType, String action) + List deviceIdentifierList, String deviceType, String action, Properties properties) throws ApplicationManagementException { DeviceManagementProviderService deviceManagementProviderService = HelperUtil .getDeviceManagementProviderService(); try { Application application = APIUtil.appDtoToAppResponse(applicationDTO); - Operation operation = generateOperationPayloadByDeviceType(deviceType, application, action); + Operation operation = generateOperationPayloadByDeviceType(deviceType, application, action, properties); return deviceManagementProviderService.addOperation(deviceType, operation, deviceIdentifierList); } catch (OperationManagementException e) { String msg = "Error occurred while adding the application install operation to devices"; @@ -1010,7 +1011,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { * @throws ApplicationManagementException if unknown application type is found to generate operation payload or * invalid action is found to generate operation payload. */ - private Operation generateOperationPayloadByDeviceType(String deviceType, Application application, String action) + private Operation generateOperationPayloadByDeviceType(String deviceType, Application application, String action, Properties properties) throws ApplicationManagementException { try { if (ApplicationType.CUSTOM.toString().equalsIgnoreCase(application.getType())) { @@ -1046,6 +1047,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager { app.setLocation(application.getApplicationReleases().get(0).getInstallerPath()); app.setIdentifier(application.getPackageName()); app.setName(application.getName()); + app.setProperties(properties); if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) { return MDMAndroidOperationUtil.createInstallAppOperation(app); } else { @@ -1067,7 +1069,6 @@ public class SubscriptionManagerImpl implements SubscriptionManager { app.setType(mobileAppType); app.setLocation(plistDownloadEndpoint); app.setIconImage(application.getApplicationReleases().get(0).getIconPath()); - Properties properties = new Properties(); properties.put(MDMAppConstants.IOSConstants.IS_PREVENT_BACKUP, true); properties.put(MDMAppConstants.IOSConstants.IS_REMOVE_APP, true); properties.put(MDMAppConstants.IOSConstants.I_TUNES_ID, application.getPackageName()); @@ -1427,4 +1428,50 @@ public class SubscriptionManagerImpl implements SubscriptionManager { ConnectionManagerUtil.closeDBConnection(); } } + + @Override + public PaginationResult getAppInstalledSubscribeDevices(PaginationRequest request, String appUUID, String subType, + String subTypeName) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + DeviceManagementProviderService deviceManagementProviderService = HelperUtil + .getDeviceManagementProviderService(); + try { + ConnectionManagerUtil.openDBConnection(); + ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(appUUID, tenantId); + int applicationReleaseId = applicationDTO.getApplicationReleaseDTOs().get(0).getId(); + List subscriptionDeviceList = new ArrayList<>(); + //todo update the API for other subscription types + if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) { + subscriptionDeviceList = subscriptionDAO + .getAppSubscribedDevicesForGroups(applicationReleaseId, subType, tenantId); + } else { + String msg = "Found invalid sub type: " + subType; + log.error(msg); + throw new NotFoundException(msg); + } + if (subscriptionDeviceList.isEmpty()) { + PaginationResult paginationResult = new PaginationResult(); + paginationResult.setData(subscriptionDeviceList); + paginationResult.setRecordsFiltered(0); + paginationResult.setRecordsTotal(0); + return paginationResult; + } + return deviceManagementProviderService.getDevicesDetails(request, subscriptionDeviceList, subTypeName); + } catch (DeviceManagementException e) { + String msg = "service error occurred while getting device data from the device management service."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred when get application release devices data for application release UUID: " + + appUUID; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "DB Connection error occurred while getting category details that given application id"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTask.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTask.java index 8a95efc0aa..d8f491e37d 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTask.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTask.java @@ -37,6 +37,7 @@ import org.wso2.carbon.device.mgt.core.task.impl.RandomlyAssignedScheduleTask; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -45,6 +46,7 @@ public class ScheduledAppSubscriptionTask extends RandomlyAssignedScheduleTask { private static final String TASK_NAME = "SCHEDULE_APP_SUBSCRIPTION"; private SubscriptionManager subscriptionManager; + private String payload; private String subscribers; private String subscriptionType; private String application; @@ -57,6 +59,7 @@ public class ScheduledAppSubscriptionTask extends RandomlyAssignedScheduleTask { @Override public void setProperties(Map map) { this.subscribers = map.get(Constants.SUBSCRIBERS); + this.payload = map.get(Constants.PAYLOAD); this.subscriptionType = map.get(Constants.SUB_TYPE); this.application = map.get(Constants.APP_UUID); this.action = map.get(Constants.ACTION); @@ -89,8 +92,9 @@ public class ScheduledAppSubscriptionTask extends RandomlyAssignedScheduleTask { new TypeToken>() { }.getType()); try { + Properties properties = new Gson().fromJson(payload, Properties.class); subscriptionManager.performBulkAppOperation(this.application, deviceIdentifiers, - this.subscriptionType, this.action); + this.subscriptionType, this.action, properties); subscriptionDTO.setStatus(ExecutionStatus.EXECUTED); } catch (ApplicationManagementException e) { log.error( @@ -102,8 +106,9 @@ public class ScheduledAppSubscriptionTask extends RandomlyAssignedScheduleTask { List subscriberList = Pattern.compile(",").splitAsStream(this.subscribers).collect( Collectors.toList()); try { + Properties properties = new Gson().fromJson(payload, Properties.class); subscriptionManager.performBulkAppOperation(this.application, subscriberList, - this.subscriptionType, this.action); + this.subscriptionType, this.action, properties); subscriptionDTO.setStatus(ExecutionStatus.EXECUTED); } catch (ApplicationManagementException e) { log.error( diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTaskManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTaskManager.java index 326a358e1b..b274b1850f 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTaskManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/task/ScheduledAppSubscriptionTaskManager.java @@ -46,6 +46,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Properties; import java.util.stream.Collectors; public class ScheduledAppSubscriptionTaskManager { @@ -73,7 +74,7 @@ public class ScheduledAppSubscriptionTaskManager { * @throws ApplicationOperationTaskException if error occurred while scheduling the subscription */ public void scheduleAppSubscriptionTask(String applicationUUID, List subscribers, - SubscriptionType subscriptionType, SubAction action, long timestamp) + SubscriptionType subscriptionType, SubAction action, long timestamp, Properties properties) throws ApplicationOperationTaskException { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date(timestamp * 1000)); @@ -106,7 +107,6 @@ public class ScheduledAppSubscriptionTaskManager { taskProperties.put(Constants.APP_UUID, applicationUUID); taskProperties.put(Constants.TENANT_DOMAIN, carbonContext.getTenantDomain(true)); taskProperties.put(Constants.SUBSCRIBER, carbonContext.getUsername()); - String subscribersString; if (SubscriptionType.DEVICE.equals(subscriptionType)) { subscribersString = new Gson().toJson(subscribers); @@ -115,6 +115,10 @@ public class ScheduledAppSubscriptionTaskManager { subscribersString = subscribers.stream().map(String.class::cast).collect(Collectors.joining(",")); taskProperties.put(Constants.SUBSCRIBERS, subscribersString); } + if(properties != null) { + String payload = new Gson().toJson(properties); + taskProperties.put(Constants.PAYLOAD, payload); + } if (log.isDebugEnabled()) { log.debug("Scheduling a task to " + action.toString() + " application: " + applicationUUID + " to/from the following " + subscriptionType.toString() + "S [" + subscribersString + "] at: " diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java index 866fbdd524..27498f77bb 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java @@ -58,6 +58,7 @@ public class Constants { public static final String SUB_TYPE = "SUBSCRIPTION_TYPE"; public static final String ACTION = "ACTION"; public static final String APP_UUID = "APP_UUID"; + public static final String APP_PROPERTIES = "APP_PROPERTIES"; public static final String SUBSCRIBER = "SUBSCRIBER"; public static final String TENANT_DOMAIN = "TENANT_DOMAIN"; public static final String TENANT_ID = "__TENANT_ID_PROP__"; 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 be55b64639..174b6921ee 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 @@ -130,7 +130,12 @@ public interface SubscriptionManagementAPI { name = "timestamp", value = "Timestamp of scheduled install/uninstall operation" ) - @QueryParam("timestamp") long timestamp + @QueryParam("timestamp") long timestamp, + @ApiParam( + name = "block-uninstall", + value = "App removal status of the install operation" + ) + @QueryParam("block-uninstall") Boolean isUninstallBlocked ); @POST @@ -183,7 +188,12 @@ public interface SubscriptionManagementAPI { name = "timestamp", value = "Timestamp of scheduled install/uninstall operation" ) - @QueryParam("timestamp") long timestamp + @QueryParam("timestamp") long timestamp, + @ApiParam( + name = "block-uninstall", + value = "App removal status of the install operation" + ) + @QueryParam("block-uninstall") Boolean isUninstallBlocked ); @POST @@ -446,4 +456,101 @@ public interface SubscriptionManagementAPI { defaultValue = "5") @QueryParam("limit") int limit ); + + @GET + @Path("/{uuid}/{subType}/{subTypeName}/devices") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Get device details in categories that have a given application install", + notes = "This will get the category's device details that have a given application install, if exists", + tags = "Subscription Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully retrieved device details.", + response = List.class, + responseContainer = "List"), + @ApiResponse( + code = 404, + message = "Not Found. \n No Devices found which has application " + + "release of UUID.", + response = ErrorResponse.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n Found invalid payload with the request.", + response = List.class), + @ApiResponse( + code = 403, + message = "Forbidden. \n Don't have permission to get the details.", + response = List.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while getting data", + response = ErrorResponse.class) + }) + Response getAppInstalledDevicesOnCategories( + @ApiParam( + name="uuid", + value="uuid of the application release.", + required = true) + @PathParam("uuid") String uuid, + @ApiParam( + name="subType", + value="Subscription type of the application release.", + required = true) + @PathParam("subType") String subType, + @ApiParam( + name="subTypeName", + value="Subscription type name of the application release.", + required = true) + @PathParam("subTypeName") String subTypeName, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many device details you require from the starting " + + "pagination index/offset.", + defaultValue = "5") + @QueryParam("limit") int limit, + @ApiParam( + name = "name", + value = "The device name. For example, Nexus devices can have names, such as shamu, bullhead or angler.", + required = false) + @Size(max = 45) + String name, + @ApiParam( + name = "user", + value = "The username of the owner of the device.", + required = false) + @QueryParam("user") + String user, + @ApiParam( + name = "ownership", + allowableValues = "BYOD, COPE", + value = "Provide the ownership status of the device. The following values can be assigned:\n" + + "- BYOD: Bring Your Own Device\n" + + "- COPE: Corporate-Owned, Personally-Enabled", + required = false) + @QueryParam("ownership") + @Size(max = 45) + String ownership, + @ApiParam( + name = "status", + value = "Provide the device status details, such as active or inactive.") + @QueryParam("status") List status + ); } 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 acf9662cb9..4a51353997 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 @@ -34,8 +34,6 @@ import org.wso2.carbon.device.application.mgt.common.BasicUserInfoList; import org.wso2.carbon.device.application.mgt.common.RoleList; import org.wso2.carbon.device.application.mgt.common.DeviceGroupList; import org.wso2.carbon.device.application.mgt.store.api.services.impl.util.RequestValidationUtil; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException; import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException; import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException; @@ -44,6 +42,9 @@ import org.wso2.carbon.device.application.mgt.core.util.APIUtil; import org.wso2.carbon.device.application.mgt.store.api.services.SubscriptionManagementAPI; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.MDMAppConstants; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; import javax.validation.Valid; import javax.ws.rs.Path; @@ -55,9 +56,8 @@ import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.core.Response; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Properties; /** * Implementation of Subscription Management related APIs. @@ -75,16 +75,22 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ @PathParam("uuid") String uuid, @PathParam("action") String action, @Valid List deviceIdentifiers, - @QueryParam("timestamp") long timestamp) { + @QueryParam("timestamp") long timestamp, + @QueryParam("block-uninstall") Boolean isUninstallBlocked + ) { + Properties properties = new Properties(); + if(isUninstallBlocked != null) { + properties.put(MDMAppConstants.AndroidConstants.IS_BLOCK_UNINSTALL, isUninstallBlocked); + } try { if (0 == timestamp) { SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); ApplicationInstallResponse response = subscriptionManager - .performBulkAppOperation(uuid, deviceIdentifiers, SubscriptionType.DEVICE.toString(), action); + .performBulkAppOperation(uuid, deviceIdentifiers, SubscriptionType.DEVICE.toString(), action, properties); return Response.status(Response.Status.OK).entity(response).build(); } else { return scheduleApplicationOperationTask(uuid, deviceIdentifiers, SubscriptionType.DEVICE, - SubAction.valueOf(action.toUpperCase()), timestamp); + SubAction.valueOf(action.toUpperCase()), timestamp, properties); } } catch (NotFoundException e) { String msg = "Couldn't found an application release for UUI: " + uuid; @@ -116,17 +122,23 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ @PathParam("subType") String subType, @PathParam("action") String action, @Valid List subscribers, - @QueryParam("timestamp") long timestamp) { + @QueryParam("timestamp") long timestamp, + @QueryParam("block-uninstall") Boolean isUninstallBlocked + ) { + Properties properties = new Properties(); + if(isUninstallBlocked != null) { + properties.put(MDMAppConstants.AndroidConstants.IS_BLOCK_UNINSTALL, isUninstallBlocked); + } try { if (0 == timestamp) { SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); ApplicationInstallResponse response = subscriptionManager - .performBulkAppOperation(uuid, subscribers, subType, action); + .performBulkAppOperation(uuid, subscribers, subType, action, properties); return Response.status(Response.Status.OK).entity(response).build(); } else { return scheduleApplicationOperationTask(uuid, subscribers, SubscriptionType.valueOf(subType.toUpperCase()), SubAction.valueOf(action.toUpperCase()), - timestamp); + timestamp, properties); } } catch (NotFoundException e) { String msg = "Couldn't found an application release for UUID: " + uuid + ". Hence, verify the payload"; @@ -170,7 +182,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ return Response.status(Response.Status.OK).entity(msg).build(); } else { return scheduleApplicationOperationTask(uuid, deviceIdentifiers, SubscriptionType.DEVICE, - SubAction.valueOf(SubAction.INSTALL.toString().toUpperCase()), timestamp); + SubAction.valueOf(SubAction.INSTALL.toString().toUpperCase()), timestamp, null); } } catch (NotFoundException e) { String msg = "Couldn't found an application release for UUI: " + uuid + " to perform ent app installation " @@ -216,7 +228,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ } else { return scheduleApplicationOperationTask(uuid, subscribers, SubscriptionType.valueOf(subType.toUpperCase()), - SubAction.valueOf(SubAction.INSTALL.toString().toUpperCase()), timestamp); + SubAction.valueOf(SubAction.INSTALL.toString().toUpperCase()), timestamp, null); } } catch (NotFoundException e) { String msg = "Couldn't found an application release for UUID: " + uuid + ". Hence, verify the payload"; @@ -255,11 +267,11 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ * @return {@link Response} of the operation */ private Response scheduleApplicationOperationTask(String applicationUUID, List subscribers, - SubscriptionType subType, SubAction subAction, long timestamp) { + SubscriptionType subType, SubAction subAction, long timestamp, Properties payload) { try { ScheduledAppSubscriptionTaskManager subscriptionTaskManager = new ScheduledAppSubscriptionTaskManager(); subscriptionTaskManager.scheduleAppSubscriptionTask(applicationUUID, subscribers, subType, subAction, - timestamp); + timestamp, payload); } catch (ApplicationOperationTaskException e) { String msg = "Error occurred while scheduling the application install operation"; log.error(msg, e); @@ -330,7 +342,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); } catch (ApplicationManagementException e) { String msg = "Error occurred while getting application with the application release uuid: " - + uuid; + + uuid; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } @@ -385,17 +397,86 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); } catch (BadRequestException e) { String msg = "Found invalid payload for getting application which has UUID: " + uuid - + ". Hence verify the payload"; + + ". 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 get the devices details."; + + "Hence you are not permitted to get the devices details."; log.error(msg, e); return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); } catch (ApplicationManagementException e) { String msg = "Error occurred while getting application with the application " + - "release uuid: " + uuid; + "release uuid: " + uuid; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @GET + @Consumes("application/json") + @Produces("application/json") + @Path("/{uuid}/{subType}/{subTypeName}/devices") + public Response getAppInstalledDevicesOnCategories( + @PathParam("uuid") String uuid, + @PathParam("subType") String subType, + @PathParam("subTypeName") String subTypeName, + @DefaultValue("0") + @QueryParam("offset") int offset, + @DefaultValue("5") + @QueryParam("limit") int limit, + @QueryParam("name") String name, + @QueryParam("user") String user, + @QueryParam("ownership") String ownership, + @QueryParam("status") List status) { + try { + SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); + PaginationRequest request = new PaginationRequest(offset, limit); + + if (StringUtils.isNotBlank(name)) { + request.setDeviceName(name); + } + if (StringUtils.isNotBlank(user)) { + request.setOwner(user); + } + if (StringUtils.isNotBlank(ownership)) { + RequestValidationUtil.validateOwnershipType(ownership); + request.setOwnership(ownership); + } + if (status != null && !status.isEmpty()) { + boolean isStatusEmpty = true; + for (String statusString : status) { + if (StringUtils.isNotBlank(statusString)) { + isStatusEmpty = false; + break; + } + } + if (!isStatusEmpty) { + RequestValidationUtil.validateStatus(status); + request.setStatusList(status); + } + } + + //todo need to update the API for other subscription types + if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) { + PaginationResult subscribedCategoryDetails = subscriptionManager + .getAppInstalledSubscribeDevices(request, uuid, subType, subTypeName); + DeviceList devices = new DeviceList(); + devices.setList((List) subscribedCategoryDetails.getData()); + devices.setCount(subscribedCategoryDetails.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(devices).build(); + } else { + String msg = "Found invalid sub type: " + subType; + log.error(msg); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } + } catch (NotFoundException e) { + String msg = "Application with application release UUID: " + uuid + " is not found"; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while getting application with the application " + + "release uuid: " + uuid; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java index f61d212493..6ad3b14bd7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.jaxrs.service.api; @@ -45,6 +61,7 @@ import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -243,6 +260,87 @@ public interface GroupManagementService { @QueryParam("requireGroupProps") boolean requireGroupProps); + + @GET + @Path("/hierarchy") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "Getting the List of Hierarchical Groups", + notes = "Returns all groups enrolled with the system hierarchically.", + tags = "Device Group Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:groups:groups") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of device hierarchical groups.", + response = DeviceGroupList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client has already the latest version of " + + "the requested resource."), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the groups list.", + response = ErrorResponse.class) + }) + Response getGroupsWithHierarchy( + @ApiParam( + name = "name", + value = "Name of the group.") + @QueryParam("name") + String name, + @ApiParam( + name = "owner", + value = "Owner of the group.") + @QueryParam("owner") + String owner, + @ApiParam( + name = "requireGroupProps", + value = "Request group properties to include in the response", + defaultValue = "false") + @QueryParam("requireGroupProps") + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.") + @DefaultValue("3") + @QueryParam("depth") + int depth, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @DefaultValue("0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many records require from the starting pagination index/offset.", + defaultValue = "5") + @DefaultValue("5") + @QueryParam("limit") + int limit); + @Path("/count") @GET @ApiOperation( @@ -412,7 +510,14 @@ public interface GroupManagementService { value = "Request group properties to include in the response", defaultValue = "false") @QueryParam("requireGroupProps") - boolean requireGroupProps); + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.", + defaultValue = "1") + @DefaultValue("1") + @QueryParam("depth") + int depth); @Path("/name/{groupName}") @GET @@ -471,7 +576,14 @@ public interface GroupManagementService { value = "Request group properties to include in the response", defaultValue = "false") @QueryParam("requireGroupProps") - boolean requireGroupProps); + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.", + defaultValue = "1") + @DefaultValue("1") + @QueryParam("depth") + int depth); @Path("/id/{groupId}") @PUT @@ -580,7 +692,12 @@ public interface GroupManagementService { name = "groupId", value = "ID of the group to be deleted.", required = true) - @PathParam("groupId") int groupId); + @PathParam("groupId") int groupId, + @ApiParam( + name = "isDeleteChildren", + value = "Is the children groups needs to be deleted.", + required = true) + @QueryParam("isDeleteChildren") boolean isDeleteChildren); @Path("/id/{groupId}/share") @POST diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java index f631b1dc51..d7b8553b20 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.jaxrs.service.api.admin; @@ -163,6 +179,90 @@ public interface GroupManagementAdminService { @QueryParam("requireGroupProps") boolean requireGroupProps); + @GET + @Path("hierarchy") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "Getting the List of Hierarchical Groups", + notes = "Returns all groups enrolled with the system hierarchically.", + tags = "Device Group Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin-groups:view") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of device groups hierarchically.", + response = DeviceGroupList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client has already the latest version of " + + "the requested resource."), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the groups list.", + response = ErrorResponse.class) + }) + Response getGroupsWithHierarchy(@ApiParam( + name = "name", + value = "Name of the group.") + @QueryParam("name") + String name, + @ApiParam( + name = "owner", + value = "Owner of the group.") + @QueryParam("owner") + String owner, + @ApiParam( + name = "status", + value = "status of group to be retrieve.") + @QueryParam("status") + String status, + @ApiParam( + name = "requireGroupProps", + value = "Request group properties to include in the response", + defaultValue = "false") + @QueryParam("requireGroupProps") + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.") + @DefaultValue("3") + @QueryParam("depth") + int depth, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @DefaultValue("0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many records require from the starting pagination index/offset.", + defaultValue = "5") + @DefaultValue("5") + @QueryParam("limit") + int limit); + @Path("/count") @GET @ApiOperation( diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java index 7648a102b8..c0a5a4a6b4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -136,6 +136,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.ArrayList; +import java.util.Properties; @Path("/devices") public class DeviceManagementServiceImpl implements DeviceManagementService { @@ -915,7 +916,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { if (UUID != null) { ApplicationInstallResponse response = subscriptionManager .performBulkAppOperation(UUID, deviceIdentifiers, SubscriptionType.DEVICE.toString(), - "uninstall"); + "uninstall", new Properties()); return Response.status(Response.Status.OK).entity(response).build(); //if the applications not installed via entgra store } else { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java index 0502f37ab3..3fed8e7504 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.jaxrs.service.impl; @@ -36,7 +52,6 @@ import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupNotExistException; import org.wso2.carbon.device.mgt.common.group.mgt.RoleDoesNotExistException; -import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceGroupList; @@ -47,10 +62,12 @@ import org.wso2.carbon.device.mgt.jaxrs.service.api.GroupManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import org.wso2.carbon.policy.mgt.common.PolicyAdministratorPoint; -import org.wso2.carbon.policy.mgt.common.PolicyEvaluationException; -import org.wso2.carbon.policy.mgt.common.PolicyEvaluationPoint; import org.wso2.carbon.policy.mgt.common.PolicyManagementException; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.util.ArrayList; import java.util.List; @@ -89,11 +106,41 @@ public class GroupManagementServiceImpl implements GroupManagementService { } } + @GET + @Path("/hierarchy") + @Override + public Response getGroupsWithHierarchy( + @QueryParam("name") String name, + @QueryParam("owner") String owner, + @QueryParam("requireGroupProps") boolean requireGroupProps, + @DefaultValue("3") @QueryParam("depth") int depth, + @DefaultValue("0") @QueryParam("offset") int offset, + @DefaultValue("5") @QueryParam("limit") int limit) { + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + String currentUser = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + GroupPaginationRequest request = new GroupPaginationRequest(offset, limit); + request.setGroupName(name); + request.setOwner(owner); + request.setDepth(depth); + PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService() + .getGroupsWithHierarchy(currentUser, request, requireGroupProps); + DeviceGroupList deviceGroupList = new DeviceGroupList(); + deviceGroupList.setList(deviceGroupsResult.getData()); + deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(deviceGroupList).build(); + } catch (GroupManagementException e) { + String error = "Error occurred while retrieving groups with hierarchy."; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Override public Response getGroupCount() { try { String currentUser = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); - int count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCount(currentUser); + int count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCount(currentUser, null); return Response.status(Response.Status.OK).entity(count).build(); } catch (GroupManagementException e) { String msg = "Error occurred while retrieving group count."; @@ -125,10 +172,10 @@ public class GroupManagementServiceImpl implements GroupManagementService { } @Override - public Response getGroup(int groupId, boolean requireGroupProps) { + public Response getGroup(int groupId, boolean requireGroupProps, int depth) { try { GroupManagementProviderService service = DeviceMgtAPIUtils.getGroupManagementProviderService(); - DeviceGroup deviceGroup = service.getGroup(groupId, requireGroupProps); + DeviceGroup deviceGroup = service.getGroup(groupId, requireGroupProps, depth); if (deviceGroup != null) { return Response.status(Response.Status.OK).entity(deviceGroup).build(); } else { @@ -142,7 +189,7 @@ public class GroupManagementServiceImpl implements GroupManagementService { } @Override - public Response getGroup(String groupName, boolean requireGroupProps) { + public Response getGroup(String groupName, boolean requireGroupProps, int depth) { try { GroupManagementProviderService service = DeviceMgtAPIUtils.getGroupManagementProviderService(); DeviceGroup deviceGroup = service.getGroup(groupName, requireGroupProps); @@ -178,9 +225,9 @@ public class GroupManagementServiceImpl implements GroupManagementService { } @Override - public Response deleteGroup(int groupId) { + public Response deleteGroup(int groupId, boolean isDeleteChildren) { try { - if (DeviceMgtAPIUtils.getGroupManagementProviderService().deleteGroup(groupId)) { + if (DeviceMgtAPIUtils.getGroupManagementProviderService().deleteGroup(groupId, isDeleteChildren)) { return Response.status(Response.Status.OK).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("Group not found.").build(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java index b742a1d8e1..a461b71b50 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.jaxrs.service.impl.admin; @@ -31,6 +47,10 @@ import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.GroupManagementAdminSe import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.util.ArrayList; @@ -74,6 +94,37 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ } } + @GET + @Path("/hierarchy") + @Override + public Response getGroupsWithHierarchy( + @QueryParam("name") String name, + @QueryParam("owner") String owner, + @QueryParam("status") String status, + @QueryParam("requireGroupProps") boolean requireGroupProps, + @DefaultValue("3") @QueryParam("depth") int depth, + @DefaultValue("0") @QueryParam("offset") int offset, + @DefaultValue("5") @QueryParam("limit") int limit) { + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + GroupPaginationRequest request = new GroupPaginationRequest(offset, limit); + request.setGroupName(name); + request.setOwner(owner); + request.setStatus(status); + request.setDepth(depth); + PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService() + .getGroupsWithHierarchy(null, request, requireGroupProps); + DeviceGroupList deviceGroupList = new DeviceGroupList(); + deviceGroupList.setList(deviceGroupsResult.getData()); + deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(deviceGroupList).build(); + } catch (GroupManagementException e) { + String error = "Error occurred while retrieving groups with hierarchy."; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Override public Response getGroupCount(String status) { try { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java index 20136b172d..2d430c09f6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java @@ -15,11 +15,26 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.jaxrs.service.impl; -import org.mockito.Mock; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; @@ -130,13 +145,14 @@ public class GroupManagementServiceImplTest { .toReturn(groupManagementProviderService); PowerMockito.stub(PowerMockito.method(PrivilegedCarbonContext.class, "getThreadLocalCarbonContext")) .toReturn(context); - Mockito.doReturn(2).when(groupManagementProviderService).getGroupCount(Mockito.anyString()); + Mockito.doReturn(2).when(groupManagementProviderService) + .getGroupCount(Mockito.anyString(), Mockito.anyString()); Response response = groupManagementService.getGroupCount(); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "GetGroupCount request failed with valid parameters"); Mockito.reset(groupManagementProviderService); Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService) - .getGroupCount(Mockito.anyString()); + .getGroupCount(Mockito.anyString(), Mockito.anyString()); response = groupManagementService.getGroupCount(); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "GetGroupCount request succeeded with in-valid parameters"); @@ -174,16 +190,16 @@ public class GroupManagementServiceImplTest { public void testGetGroup() throws GroupManagementException { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getGroupManagementProviderService")) .toReturn(groupManagementProviderService); - Mockito.doReturn(new DeviceGroup()).when(groupManagementProviderService).getGroup(1, false); - Mockito.doReturn(null).when(groupManagementProviderService).getGroup(2, false); - Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).getGroup(3, false); - Response response = groupManagementService.getGroup(1, false); + Mockito.doReturn(new DeviceGroup()).when(groupManagementProviderService).getGroup(1, false, 1); + Mockito.doReturn(null).when(groupManagementProviderService).getGroup(2, false, 1); + Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).getGroup(3, false, 1); + Response response = groupManagementService.getGroup(1, false, 1); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "getGroup request failed for a request with valid parameters"); - response = groupManagementService.getGroup(2, false); + response = groupManagementService.getGroup(2, false, 1); Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode(), "getGroup request returned a group for a non-existing group"); - response = groupManagementService.getGroup(3, false); + response = groupManagementService.getGroup(3, false, 1); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "getGroup request returned a group for a in-valid request"); } @@ -216,16 +232,16 @@ public class GroupManagementServiceImplTest { public void testDeleteGroup() throws GroupManagementException { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getGroupManagementProviderService")) .toReturn(groupManagementProviderService); - Mockito.doReturn(true).when(groupManagementProviderService).deleteGroup(1); - Mockito.doReturn(false).when(groupManagementProviderService).deleteGroup(2); - Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).deleteGroup(3); - Response response = groupManagementService.deleteGroup(1); + Mockito.doReturn(true).when(groupManagementProviderService).deleteGroup(1, false); + Mockito.doReturn(false).when(groupManagementProviderService).deleteGroup(2, false); + Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).deleteGroup(3, false); + Response response = groupManagementService.deleteGroup(1, false); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "delete group request failed for a request with valid parameters"); - response = groupManagementService.deleteGroup(2); + response = groupManagementService.deleteGroup(2, false); Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode(), "Non-existing group was successfully deleted"); - response = groupManagementService.deleteGroup(3); + response = groupManagementService.deleteGroup(3, false); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Deletion succeeded with an erroneous condition."); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java index d7a74f199b..9402d2ab37 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.common; @@ -28,6 +45,8 @@ public class GroupPaginationRequest { private String owner; private String groupName; private String status; + private String parentPath; + private int depth; public GroupPaginationRequest(int start, int rowCount) { this.startIndex = start; @@ -74,6 +93,22 @@ public class GroupPaginationRequest { this.groupName = groupName; } + public String getParentPath() { + return parentPath; + } + + public void setParentPath(String parentPath) { + this.parentPath = parentPath; + } + + public int getDepth() { + return depth; + } + + public void setDepth(int depth) { + this.depth = depth; + } + @Override public String toString() { return "Group Name '" + this.groupName + "' num of rows: " + this.rowCount + " start index: " + this.startIndex diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/MDMAppConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/MDMAppConstants.java index e7f8f17df7..40b647d6ea 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/MDMAppConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/MDMAppConstants.java @@ -45,6 +45,7 @@ public class MDMAppConstants { private AndroidConstants() { throw new AssertionError(); } + public static final String IS_BLOCK_UNINSTALL = "isBlockUninstall"; public static final String OPCODE_INSTALL_APPLICATION = "INSTALL_APPLICATION"; public static final String OPCODE_UNINSTALL_APPLICATION = "UNINSTALL_APPLICATION"; public static final String UNMANAGED_APP_UNINSTALL= "UNMANAGED_APP_UNINSTALL"; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/AppStoreApplication.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/AppStoreApplication.java index 50126814ca..71464070b7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/AppStoreApplication.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/AppStoreApplication.java @@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.common.app.mgt.android; import com.google.gson.Gson; import java.io.Serializable; +import java.util.Properties; /** * This class represents the Appstore AuthenticationImpl information. @@ -29,6 +30,7 @@ public class AppStoreApplication implements Serializable { private String type; private String appIdentifier; + private Properties properties; public String getType() { return type; @@ -51,4 +53,11 @@ public class AppStoreApplication implements Serializable { return gson.toJson(this); } + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/EnterpriseApplication.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/EnterpriseApplication.java index f087013a18..0e9bdb47da 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/EnterpriseApplication.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/EnterpriseApplication.java @@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.common.app.mgt.android; import com.google.gson.Gson; import java.io.Serializable; +import java.util.Properties; /** * This class represents the Enterprise AuthenticationImpl information. @@ -30,6 +31,7 @@ public class EnterpriseApplication implements Serializable { private String type; private String url; private String appIdentifier; + private Properties properties; public String getAppIdentifier() { return appIdentifier; @@ -60,4 +62,11 @@ public class EnterpriseApplication implements Serializable { return gson.toJson(this); } + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/WebApplication.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/WebApplication.java index 3257429269..70797dc8d9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/WebApplication.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/app/mgt/android/WebApplication.java @@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.common.app.mgt.android; import com.google.gson.Gson; import java.io.Serializable; +import java.util.Properties; /** * This class represents the Web AuthenticationImpl information. @@ -30,6 +31,7 @@ public class WebApplication implements Serializable { private String name; private String url; private String type; + private Properties properties; public String getName() { return name; @@ -60,4 +62,11 @@ public class WebApplication implements Serializable { return gson.toJson(this); } + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java index 20ed01fb49..a3511033d5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.common.group.mgt; @@ -21,6 +38,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; +import java.util.List; import java.util.Map; /** @@ -47,6 +65,15 @@ public class DeviceGroup implements Serializable { @ApiModelProperty(name = "status", value = "The status of group that needs updating/retrieval.") private String status; + @ApiModelProperty(name = "parentGroupId", value = "Group ID of parent group") + private int parentGroupId; + + @ApiModelProperty(name = "parentPath", value = "Path of parent group") + private String parentPath; + + @ApiModelProperty(name = "childrenGroups", value = "Children groups") + private List childrenGroups; + public String getStatus() { return status; } @@ -103,4 +130,27 @@ public class DeviceGroup implements Serializable { this.groupProperties = groupProperties; } + public int getParentGroupId() { + return parentGroupId; + } + + public void setParentGroupId(int parentGroupId) { + this.parentGroupId = parentGroupId; + } + + public String getParentPath() { + return parentPath; + } + + public void setParentPath(String parentPath) { + this.parentPath = parentPath; + } + + public List getChildrenGroups() { + return childrenGroups; + } + + public void setChildrenGroups(List childrenGroups) { + this.childrenGroups = childrenGroups; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java index 039219bfe8..b1a185d98f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java @@ -84,4 +84,8 @@ public class DeviceGroupConstants { public static final String[] DEFAULT_VIEW_EVENTS_PERMISSIONS = {"/permission/device-mgt/user/groups/device_events"}; } + + public static final class HierarchicalGroup { + public static final String SEPERATOR = "/"; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java index 77b9d76c5c..9796dd40f4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java @@ -758,4 +758,27 @@ public interface DeviceDAO { String version) throws DeviceManagementDAOException; int getFunctioningDevicesInSystem() throws DeviceManagementDAOException; + + /** + * This method is used to get the details of devices when give deviceIDs list and group name. + * @param deviceIds device ids of the devices. + * @param tenantId Id of the current tenant. + * @param request paginated request object. + * @param groupName group name. + * @return devices - device details list + * @throws DeviceManagementDAOException if connections establishment fails. + */ + List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException; + + /** + * @param deviceIds device ids of the devices. + * @param tenantId tenant id + * @param request paginated request object. + * @param groupName group name. + * @return number of device count under the group name. + * @throws DeviceManagementDAOException if error occurred while processing the SQL statement. + */ + int getGroupedDevicesCount(PaginationRequest request, List deviceIds, String groupName, int tenantId) + throws DeviceManagementDAOException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java index 79b536feaa..9ba4e36283 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao; @@ -74,6 +91,15 @@ public interface GroupDAO { */ void deleteAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Remove properties of device groups. + * + * @param groupIds to be deleted. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during deletion of group properties of groups + */ + void deleteAllGroupsProperties(List groupIds, int tenantId) throws GroupManagementDAOException; + /** * Retrives all properties stored against a group. * @@ -95,6 +121,15 @@ public interface GroupDAO { void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Update existing Device Groups. + * + * @param deviceGroups groups to update. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during updating of groups + */ + void updateGroups(List deviceGroups, int tenantId) throws GroupManagementDAOException; + /** * Delete an existing Device Group. * @@ -104,6 +139,24 @@ public interface GroupDAO { */ void deleteGroup(int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Delete mappings of Device Groups. + * + * @param groupIds of Device Groups. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during deletion of mappings of groups + */ + void deleteGroupsMapping(List groupIds, int tenantId) throws GroupManagementDAOException; + + /** + * Delete existing Device Groups. + * + * @param groupIds of Device Groups. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during deletion of groups + */ + void deleteGroups(List groupIds, int tenantId) throws GroupManagementDAOException; + /** * Get device group by id. * @@ -114,6 +167,25 @@ public interface GroupDAO { */ DeviceGroup getGroup(int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Get children groups by parent path. + * + * @param parentPath of parent group. + * @param tenantId of the group. + * @return {@link List} list of children device groups + * @throws GroupManagementDAOException on error during retrieval of children groups + */ + List getChildrenGroups(String parentPath, int tenantId) throws GroupManagementDAOException; + + /** + * Get root groups. + * + * @param tenantId of the group. + * @return {@link List} list of root device groups + * @throws GroupManagementDAOException on error during retrieval of root groups + */ + List getRootGroups(int tenantId) throws GroupManagementDAOException; + /** * Get the groups of device with device id provided * @param deviceId @@ -306,10 +378,11 @@ public interface GroupDAO { * * @param roles of the group. * @param tenantId of user's tenant. + * @param parentPath of the group. * @return count of device groups. * @throws GroupManagementDAOException */ - int getGroupsCount(String[] roles, int tenantId) throws GroupManagementDAOException; + int getGroupsCount(String[] roles, int tenantId, String parentPath) throws GroupManagementDAOException; /** * Get all device groups which owned by user. @@ -336,10 +409,11 @@ public interface GroupDAO { * * @param username of the owner. * @param tenantId of user's tenant. + * @param parentPath of the group. * @return count of device groups. * @throws GroupManagementDAOException */ - int getOwnGroupsCount(String username, int tenantId) throws GroupManagementDAOException; + int getOwnGroupsCount(String username, int tenantId, String parentPath) throws GroupManagementDAOException; /** * Get device Ids of devices which are assigned to groups. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index bf387744e2..dd175d493a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -3022,4 +3022,154 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { throw new DeviceManagementDAOException(msg, e); } } + + @Override + public List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + int limitValue = request.getRowCount(); + int offsetValue = request.getStartIndex(); + List status = request.getStatusList(); + String name = request.getDeviceName(); + String user = request.getOwner(); + String ownership = request.getOwnership(); + try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } + Connection conn = this.getConnection(); + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "DM_DEVICE.ID AS DEVICE_ID, " + + "DM_DEVICE.NAME AS DEVICE_NAME, " + + "DM_DEVICE.DESCRIPTION AS DESCRIPTION, " + + "DM_DEVICE.DEVICE_TYPE_ID, " + + "DM_DEVICE.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.DATE_OF_ENROLMENT, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.STATUS, " + + "e.IS_TRANSFERRED, " + + "device_types.NAME AS DEVICE_TYPE " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_DEVICE ON " + + "DM_DEVICE_GROUP_MAP.DEVICE_ID = DM_DEVICE.ID " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "INNER JOIN DM_ENROLMENT e ON " + + "DM_DEVICE.ID = e.DEVICE_ID AND " + + "DM_DEVICE.TENANT_ID = e.TENANT_ID " + + "INNER JOIN (SELECT ID, NAME FROM DM_DEVICE_TYPE) AS device_types ON " + + "device_types.ID = DM_DEVICE.DEVICE_TYPE_ID " + + "WHERE DM_DEVICE.ID IN (", + ") AND DM_DEVICE.TENANT_ID = ?"); + + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + if (StringUtils.isNotBlank(name)) { + query += " AND DM_DEVICE.NAME LIKE ?"; + } + if (StringUtils.isNotBlank(user)) { + query += " AND e.OWNER = ?"; + } + if (StringUtils.isNotBlank(ownership)) { + query += " AND e.OWNERSHIP = ?"; + } + if (status != null && !status.isEmpty()) { + query += buildStatusQuery(status); + } + + query += "LIMIT ? OFFSET ?"; + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index++, groupName); + } + if (StringUtils.isNotBlank(name)) { + ps.setString(index++, name); + } + if (StringUtils.isNotBlank(user)) { + ps.setString(index++, user); + } + if (StringUtils.isNotBlank(ownership)) { + ps.setString(index++, ownership); + } + if (status != null && !status.isEmpty()) { + for (String deviceStatus : status) { + ps.setString(index++, deviceStatus); + } + } + ps.setInt(index++, limitValue); + ps.setInt(index, offsetValue); + + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + devices.add(DeviceManagementDAOUtil.loadDevice(rs)); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getGroupedDevicesCount(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + if (deviceIds.isEmpty()) { + return 0; + } + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "COUNT(DM_DEVICE_GROUP_MAP.DEVICE_ID) AS DEVICE_COUNT " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "WHERE DM_DEVICE_GROUP_MAP.DEVICE_ID IN (", + ") AND DM_GROUP.TENANT_ID = ?"); + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index, groupName); + } + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("DEVICE_COUNT"); + } + return 0; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java index 04d4bce584..c3426e3521 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java @@ -14,18 +14,34 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao.impl; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.solr.common.StringUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; -import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupDAO; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; @@ -49,6 +65,127 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { private static final Log log = LogFactory.getLog(AbstractGroupDAOImpl.class); + @Override + public List getGroups(GroupPaginationRequest request, int tenantId) + throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; + if (StringUtils.isNotBlank(request.getGroupName())) { + sql += " AND UPPER(GROUP_NAME) LIKE ?"; + } + if (StringUtils.isNotBlank(request.getOwner())) { + sql += " AND UPPER(OWNER) LIKE ?"; + } + if (StringUtils.isNotBlank(request.getStatus())) { + sql += " AND STATUS = ?"; + } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } + if (request.getRowCount() != 0) { + sql += " LIMIT ? OFFSET ?"; + } + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int paramIndex = 1; + stmt.setInt(paramIndex++, tenantId); + if (StringUtils.isNotBlank(request.getGroupName())) { + stmt.setString(paramIndex++, request.getGroupName() + "%"); + } + if (StringUtils.isNotBlank(request.getOwner())) { + stmt.setString(paramIndex++, request.getOwner() + "%"); + } + if (StringUtils.isNotBlank(request.getStatus())) { + stmt.setString(paramIndex++, request.getStatus().toUpperCase()); + } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } + if (request.getRowCount() != 0) { + stmt.setInt(paramIndex++, request.getRowCount()); + stmt.setInt(paramIndex, request.getStartIndex()); + } + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving groups in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + + @Override + public List getGroups(GroupPaginationRequest request, List deviceGroupIds, + int tenantId) throws GroupManagementDAOException { + int deviceGroupIdsCount = deviceGroupIds.size(); + if (deviceGroupIdsCount == 0) { + return new ArrayList<>(); + } + + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP WHERE TENANT_ID = ?"; + if (StringUtils.isNotBlank(request.getGroupName())) { + sql += " AND GROUP_NAME LIKE ?"; + } + if (StringUtils.isNotBlank(request.getOwner())) { + sql += " AND OWNER LIKE ?"; + } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } + sql += " AND ID IN ("; + for (int i = 0; i < deviceGroupIdsCount; i++) { + sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; + } + sql += ")"; + if (request.getRowCount() != 0) { + sql += " LIMIT ? OFFSET ?"; + } + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int paramIndex = 1; + stmt.setInt(paramIndex++, tenantId); + if (StringUtils.isNotBlank(request.getGroupName())) { + stmt.setString(paramIndex++, request.getGroupName() + "%"); + } + if (StringUtils.isNotBlank(request.getOwner())) { + stmt.setString(paramIndex++, request.getOwner() + "%"); + } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } + for (Integer deviceGroupId : deviceGroupIds) { + stmt.setInt(paramIndex++, deviceGroupId); + } + if (request.getRowCount() != 0) { + stmt.setInt(paramIndex++, request.getRowCount()); + stmt.setInt(paramIndex, request.getStartIndex()); + } + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving groups of groups IDs " + deviceGroupIds.toString() + + " in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + @Override public int addGroup(DeviceGroup deviceGroup, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -59,9 +196,11 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { Connection conn = GroupManagementDAOFactory.getConnection(); String sql; if (deviceGroup.getStatus() == null || deviceGroup.getStatus().isEmpty()) { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) VALUES (?, ?, ?, ?)"; + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH) " + + "VALUES (?, ?, ?, ?, ?)"; } else { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, STATUS) VALUES (?, ?, ?, ?, ?)"; + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH, STATUS) " + + "VALUES (?, ?, ?, ?, ?, ?)"; hasStatus = true; } stmt = conn.prepareStatement(sql, new String[]{"ID"}); @@ -69,8 +208,9 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(2, deviceGroup.getName()); stmt.setString(3, deviceGroup.getOwner()); stmt.setInt(4, tenantId); + stmt.setString(5, deviceGroup.getParentPath()); if (hasStatus) { - stmt.setString(5, deviceGroup.getStatus()); + stmt.setString(6, deviceGroup.getStatus()); } stmt.executeUpdate(); @@ -151,10 +291,12 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { try { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = - "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ? WHERE ID = ? AND TENANT_ID = ?"; + "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, PARENT_PATH = ? WHERE ID = ? " + + "AND TENANT_ID = ?"; if (deviceGroup.getStatus() != null && !deviceGroup.getStatus().isEmpty()) { - sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, STATUS = ? WHERE ID = ? AND TENANT_ID = ?"; + sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, PARENT_PATH = ?, STATUS = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; hasStatus = true; } stmt = conn.prepareStatement(sql); @@ -162,11 +304,12 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(paramIndex++, deviceGroup.getDescription()); stmt.setString(paramIndex++, deviceGroup.getName()); stmt.setString(paramIndex++, deviceGroup.getOwner()); + stmt.setString(paramIndex++, deviceGroup.getParentPath()); if (hasStatus) { stmt.setString(paramIndex++, deviceGroup.getStatus()); } stmt.setInt(paramIndex++, groupId); - stmt.setInt(paramIndex++, tenantId); + stmt.setInt(paramIndex, tenantId); stmt.executeUpdate(); } catch (SQLException e) { throw new GroupManagementDAOException("Error occurred while updating deviceGroup '" + @@ -176,6 +319,32 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + @Override + public void updateGroups(List deviceGroups, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, STATUS = ?, " + + "PARENT_PATH = ? WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + for (DeviceGroup deviceGroup : deviceGroups) { + stmt.setString(1, deviceGroup.getDescription()); + stmt.setString(2, deviceGroup.getName()); + stmt.setString(3, deviceGroup.getOwner()); + stmt.setString(4, deviceGroup.getStatus()); + stmt.setString(5, deviceGroup.getParentPath()); + stmt.setInt(6, deviceGroup.getGroupId()); + stmt.setInt(7, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while updating groups as batch"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + @Override public void deleteGroup(int groupId, int tenantId) throws GroupManagementDAOException { Connection conn; @@ -217,6 +386,64 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + @Override + public void deleteGroupsMapping(List groupIds, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "DELETE FROM DM_ROLE_GROUP_MAP WHERE GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + sql = "DELETE FROM DM_DEVICE_GROUP_MAP WHERE GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + sql = "DELETE FROM DM_DEVICE_GROUP_POLICY WHERE DEVICE_GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while removing mappings of groups as batches"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + + @Override + public void deleteGroups(List groupIds, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "DELETE FROM DM_GROUP WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting groups as batches"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + public void deleteAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -235,6 +462,25 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + public void deleteAllGroupsProperties(List groupIds, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "DELETE FROM GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting properties of groups as batches"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + public Map getAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -266,7 +512,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { ResultSet resultSet = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE ID = ? AND TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP WHERE ID = ? " + + "AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setInt(1, groupId); stmt.setInt(2, tenantId); @@ -284,6 +531,56 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + @Override + public List getChildrenGroups(String parentPath, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE PARENT_PATH LIKE ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, parentPath + "%"); + stmt.setInt(2, tenantId); + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving children group having parent path '" + parentPath + + "' in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + + @Override + public List getRootGroups(int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE PARENT_PATH LIKE ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, "/"); + stmt.setInt(2, tenantId); + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + deviceGroupList = new ArrayList<>(); + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving root groups in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + @Override public List getGroups(int deviceId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -291,7 +588,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupBuilders = new ArrayList<>(); try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT G.ID, G.GROUP_NAME, G.DESCRIPTION, G.OWNER, G.STATUS FROM DM_GROUP G " + + String sql = "SELECT G.ID, G.GROUP_NAME, G.DESCRIPTION, G.OWNER, G.STATUS, G.PARENT_PATH FROM DM_GROUP G " + "INNER JOIN DM_DEVICE_GROUP_MAP GM ON G.ID = GM.GROUP_ID " + "WHERE GM.DEVICE_ID = ? AND GM.TENANT_ID = ?"; stmt = conn.prepareStatement(sql); @@ -316,7 +613,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupList = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setInt(1, tenantId); resultSet = stmt.executeQuery(); @@ -389,6 +687,9 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { sql += " AND STATUS = ?"; hasStatus = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH = ?"; + } int paramIndex = 1; stmt = conn.prepareStatement(sql); @@ -397,10 +698,13 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(paramIndex++, groupName + "%"); } if (hasOwner) { - stmt.setString(paramIndex, owner + "%"); + stmt.setString(paramIndex++, owner + "%"); } if (hasStatus) { - stmt.setString(paramIndex, request.getStatus()); + stmt.setString(paramIndex++, request.getStatus()); + } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex, request.getParentPath()); } resultSet = stmt.executeQuery(); if (resultSet.next()) { @@ -422,7 +726,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { try { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = - "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE GROUP_NAME = ? AND TENANT_ID = ?"; + "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE GROUP_NAME = ? AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setString(1, groupName); stmt.setInt(2, tenantId); @@ -592,7 +897,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupList = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP g, " + + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP g, " + "(SELECT GROUP_ID FROM DM_ROLE_GROUP_MAP WHERE ROLE IN ("; int index = 0; @@ -658,7 +963,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } @Override - public int getGroupsCount(String[] roles, int tenantId) throws GroupManagementDAOException { + public int getGroupsCount(String[] roles, int tenantId, String parentPath) throws GroupManagementDAOException { int rolesCount = roles.length; if (rolesCount == 0) { return 0; @@ -672,14 +977,20 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { for (int i = 0; i < rolesCount; i++) { sql += (rolesCount - 1 != i) ? "?," : "?"; } - sql += ")) gr WHERE g.ID = gr.GROUP_ID AND TENANT_ID = ? GROUP BY g.ID"; - + sql += ")) gr WHERE g.ID = gr.GROUP_ID AND TENANT_ID = ? "; + if (StringUtils.isNotBlank(parentPath)) { + sql += " AND g.PARENT_PATH = ? "; + } + sql += "GROUP BY g.ID"; stmt = conn.prepareStatement(sql); int index = 0; while (index++ < rolesCount) { stmt.setString(index, roles[index - 1]); } - stmt.setInt(index, tenantId); + stmt.setInt(index++, tenantId); + if (StringUtils.isNotBlank(parentPath)) { + stmt.setString(index, parentPath); + } resultSet = stmt.executeQuery(); if (resultSet.next()) { return resultSet.getInt("GROUP_COUNT"); @@ -700,7 +1011,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupList = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE OWNER = ? AND TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE OWNER = ? AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setString(1, username); stmt.setInt(2, tenantId); @@ -744,15 +1056,21 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } @Override - public int getOwnGroupsCount(String username, int tenantId) throws GroupManagementDAOException { + public int getOwnGroupsCount(String username, int tenantId, String parentPath) throws GroupManagementDAOException { PreparedStatement stmt = null; ResultSet resultSet = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = "SELECT COUNT(ID) AS GROUP_COUNT FROM DM_GROUP WHERE OWNER = ? AND TENANT_ID = ?"; + if (StringUtils.isNotBlank(parentPath)) { + sql += " AND PARENT_PATH = ?"; + } stmt = conn.prepareStatement(sql); stmt.setString(1, username); stmt.setInt(2, tenantId); + if (StringUtils.isNotBlank(parentPath)) { + stmt.setString(3, parentPath); + } resultSet = stmt.executeQuery(); if (resultSet.next()) { return resultSet.getInt("GROUP_COUNT"); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index 4393a4546e..f2a91cae45 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -1194,6 +1194,79 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + int limitValue = request.getRowCount(); + int offsetValue = request.getStartIndex(); + try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } + Connection conn = this.getConnection(); + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "DM_DEVICE.ID AS DEVICE_ID, " + + "DM_DEVICE.NAME AS DEVICE_NAME, " + + "DM_DEVICE.DESCRIPTION AS DESCRIPTION, " + + "DM_DEVICE.DEVICE_TYPE_ID, " + + "DM_DEVICE.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.DATE_OF_ENROLMENT, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.STATUS, " + + "e.IS_TRANSFERRED, " + + "device_types.NAME AS DEVICE_TYPE " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_DEVICE ON " + + "DM_DEVICE_GROUP_MAP.DEVICE_ID = DM_DEVICE.ID " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "INNER JOIN DM_ENROLMENT e ON " + + "DM_DEVICE.ID = e.DEVICE_ID AND " + + "DM_DEVICE.TENANT_ID = e.TENANT_ID " + + "INNER JOIN (SELECT ID, NAME FROM DM_DEVICE_TYPE) AS device_types ON " + + "device_types.ID = DM_DEVICE.DEVICE_TYPE_ID " + + "WHERE DM_DEVICE.ID IN (", + ") AND DM_DEVICE.TENANT_ID = ?"); + + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + query += " ORDER BY DEVICE_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index++, groupName); + } + ps.setInt(index++, offsetValue); + ps.setInt(index, limitValue); + + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + devices.add(DeviceManagementDAOUtil.loadDevice(rs)); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 8911beca49..ae4b25b431 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -18,6 +18,7 @@ package org.wso2.carbon.device.mgt.core.dao.impl.device; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; @@ -1132,6 +1133,79 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + int limitValue = request.getRowCount(); + int offsetValue = request.getStartIndex(); + try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } + Connection conn = this.getConnection(); + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "DM_DEVICE.ID AS DEVICE_ID, " + + "DM_DEVICE.NAME AS DEVICE_NAME, " + + "DM_DEVICE.DESCRIPTION AS DESCRIPTION, " + + "DM_DEVICE.DEVICE_TYPE_ID, " + + "DM_DEVICE.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.DATE_OF_ENROLMENT, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.STATUS, " + + "e.IS_TRANSFERRED, " + + "device_types.NAME AS DEVICE_TYPE " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_DEVICE ON " + + "DM_DEVICE_GROUP_MAP.DEVICE_ID = DM_DEVICE.ID " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "INNER JOIN DM_ENROLMENT e ON " + + "DM_DEVICE.ID = e.DEVICE_ID AND " + + "DM_DEVICE.TENANT_ID = e.TENANT_ID " + + "INNER JOIN (SELECT ID, NAME FROM DM_DEVICE_TYPE) AS device_types ON " + + "device_types.ID = DM_DEVICE.DEVICE_TYPE_ID " + + "WHERE DM_DEVICE.ID IN (", + ") AND DM_DEVICE.TENANT_ID = ?"); + + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + query += " ORDER BY DEVICE_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index++, groupName); + } + ps.setInt(index++, offsetValue); + ps.setInt(index, limitValue); + + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + devices.add(DeviceManagementDAOUtil.loadDevice(rs)); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + //TODO: Override for MSSQL /* @Override diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java index d980e9e0ab..96ca67edd0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java @@ -14,18 +14,32 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao.impl.group; import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; -import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGroupDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; -import org.wso2.carbon.device.mgt.core.dao.util.GroupManagementDAOUtil; import java.sql.Connection; import java.sql.PreparedStatement; @@ -38,134 +52,6 @@ import java.util.List; * This class represents implementation of GroupDAO */ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl { - @Override - public List getGroups(GroupPaginationRequest request, int tenantId) - throws GroupManagementDAOException { - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - String status = request.getStatus(); - boolean hasOwner = false; - boolean hasStatus = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND UPPER(GROUP_NAME) LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND UPPER(OWNER) LIKE ?"; - hasOwner = true; - } - if (status != null && !status.isEmpty()) { - sql += " AND STATUS = ?"; - hasStatus = true; - } - if (hasLimit) { - sql += " LIMIT ?, ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - if (hasStatus) { - stmt.setString(paramIndex++, status.toUpperCase()); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getStartIndex()); - stmt.setInt(paramIndex, request.getRowCount()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } - - @Override - public List getGroups(GroupPaginationRequest request, List deviceGroupIds, - int tenantId) throws GroupManagementDAOException { - int deviceGroupIdsCount = deviceGroupIds.size(); - if (deviceGroupIdsCount == 0) { - return new ArrayList<>(); - } - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - boolean hasOwner = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND GROUP_NAME LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND OWNER LIKE ?"; - hasOwner = true; - } - sql += " AND ID IN ("; - for (int i = 0; i < deviceGroupIdsCount; i++) { - sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; - } - sql += ")"; - if (hasLimit) { - sql += " LIMIT ?, ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - for (Integer deviceGroupId : deviceGroupIds) { - stmt.setInt(paramIndex++, deviceGroupId); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getStartIndex()); - stmt.setInt(paramIndex, request.getRowCount()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } @Override public List getDevices(int groupId, int startIndex, int rowCount, int tenantId) @@ -209,4 +95,4 @@ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java index 4074840e0f..e7473b6b53 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java @@ -14,10 +14,28 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao.impl.group; +import org.apache.commons.lang.StringUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; @@ -56,7 +74,8 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -69,6 +88,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND STATUS = ?"; hasStatus = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } if (hasLimit) { sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; } @@ -85,6 +107,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { if (hasStatus) { stmt.setString(paramIndex++, status.toUpperCase()); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } if (hasLimit) { stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex, request.getRowCount()); @@ -121,7 +146,8 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -130,6 +156,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND OWNER LIKE ?"; hasOwner = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } sql += " AND ID IN ("; for (int i = 0; i < deviceGroupIdsCount; i++) { sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; @@ -148,6 +177,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { if (hasOwner) { stmt.setString(paramIndex++, owner + "%"); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } for (Integer deviceGroupId : deviceGroupIds) { stmt.setInt(paramIndex++, deviceGroupId); } @@ -210,4 +242,4 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java index 4140a5c48a..a01ef5b6b8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java @@ -14,13 +14,29 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao.impl.group; import org.apache.solr.common.StringUtils; import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; @@ -50,10 +66,10 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { Connection conn = GroupManagementDAOFactory.getConnection(); String sql; if(StringUtils.isEmpty(deviceGroup.getStatus())) { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) " + + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH) " + "VALUES (?, ?, ?, ?) RETURNING ID"; } else { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, STATUS) " + + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH, STATUS) " + "VALUES (?, ?, ?, ?, ?) RETURNING ID"; hasStatus = true; } @@ -62,8 +78,9 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { stmt.setString(2, deviceGroup.getName()); stmt.setString(3, deviceGroup.getOwner()); stmt.setInt(4, tenantId); + stmt.setString(5, deviceGroup.getParentPath()); if(hasStatus) { - stmt.setString(5, deviceGroup.getStatus()); + stmt.setString(6, deviceGroup.getStatus()); } stmt.execute(); rs = stmt.getGeneratedKeys(); @@ -79,135 +96,6 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { } } - @Override - public List getGroups(GroupPaginationRequest request, int tenantId) - throws GroupManagementDAOException { - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - String status = request.getStatus(); - boolean hasOwner = false; - boolean hasStatus = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND GROUP_NAME LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND OWNER LIKE ?"; - hasOwner = true; - } - if (status != null && !status.isEmpty()) { - sql += " AND STATUS = ?"; - hasStatus = true; - } - if (hasLimit) { - sql += " LIMIT ? OFFSET ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - if (hasStatus) { - stmt.setString(paramIndex++, status.toUpperCase()); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getRowCount()); - stmt.setInt(paramIndex, request.getStartIndex()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } - - @Override - public List getGroups(GroupPaginationRequest request, List deviceGroupIds, - int tenantId) throws GroupManagementDAOException { - int deviceGroupIdsCount = deviceGroupIds.size(); - if (deviceGroupIdsCount == 0) { - return new ArrayList<>(); - } - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - boolean hasOwner = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND GROUP_NAME LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND OWNER LIKE ?"; - hasOwner = true; - } - sql += " AND ID IN ("; - for (int i = 0; i < deviceGroupIdsCount; i++) { - sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; - } - sql += ")"; - if (hasLimit) { - sql += " LIMIT ? OFFSET ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - for (Integer deviceGroupId : deviceGroupIds) { - stmt.setInt(paramIndex++, deviceGroupId); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getRowCount()); - stmt.setInt(paramIndex, request.getStartIndex()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } - @Override public List getDevices(int groupId, int startIndex, int rowCount, int tenantId) throws GroupManagementDAOException { @@ -250,4 +138,4 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java index 879d450349..5065628b08 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java @@ -14,10 +14,28 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao.impl.group; +import org.apache.commons.lang.StringUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; @@ -56,7 +74,8 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -69,6 +88,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND STATUS = ?"; hasStatus = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } if (hasLimit) { sql += " ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; } @@ -85,6 +107,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { if (hasStatus) { stmt.setString(paramIndex++, status.toUpperCase()); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } if (hasLimit) { stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex, request.getRowCount()); @@ -121,7 +146,8 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -130,6 +156,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND OWNER LIKE ?"; hasOwner = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } sql += " AND ID IN ("; for (int i = 0; i < deviceGroupIdsCount; i++) { sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; @@ -148,6 +177,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { if (hasOwner) { stmt.setString(paramIndex++, owner + "%"); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } for (Integer deviceGroupId : deviceGroupIds) { stmt.setInt(paramIndex++, deviceGroupId); } @@ -210,4 +242,4 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java index b3acd1d313..3025fb6d0a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java @@ -14,6 +14,22 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.dao.util; @@ -86,6 +102,7 @@ public final class GroupManagementDAOUtil { group.setName(resultSet.getString("GROUP_NAME")); group.setOwner(resultSet.getString("OWNER")); group.setStatus(resultSet.getString("STATUS")); + group.setParentPath(resultSet.getString("PARENT_PATH")); return group; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java index 533b1cb1bc..7d2ff24875 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java @@ -315,7 +315,7 @@ public class ReportManagementServiceImpl implements ReportManagementService { } //Map date blocks and counts resultObject.addProperty( - dateFormat.format(endDate) + " - " + dateFormat.format(previousDate), sum); + dateFormat.format(previousDate) + " - " + dateFormat.format(endDate), sum); endDate = previousDate; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index 6ff661568c..6265384aad 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -992,4 +992,14 @@ public interface DeviceManagementProviderService { License getLicenseConfig (String deviceTypeName) throws DeviceManagementException; + /** + * This method retrieves a list of devices details. + * @param request paginated request object. + * @param devicesIds devices ids list + * @param groupName name of the group + * @return {@link PaginationResult} + * @throws DeviceManagementException if any service level or DAO level error occurs. + */ + PaginationResult getDevicesDetails(PaginationRequest request, List devicesIds, String groupName) + throws DeviceManagementException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 1f4bac57d1..70cbee4731 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -4429,4 +4429,39 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return deviceManagementService.getLicenseConfig(); } + @Override + public PaginationResult getDevicesDetails(PaginationRequest request, List devicesIds, + String groupName) throws DeviceManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + if (log.isDebugEnabled()) { + log.debug("Getting all devices details for device ids: " + devicesIds); + } + PaginationResult paginationResult = new PaginationResult(); + List subscribedDeviceDetails; + try { + DeviceManagementDAOFactory.openConnection(); + subscribedDeviceDetails = deviceDAO.getGroupedDevicesDetails(request, devicesIds, groupName, tenantId); + if (subscribedDeviceDetails.isEmpty()) { + paginationResult.setData(new ArrayList<>()); + paginationResult.setRecordsFiltered(0); + paginationResult.setRecordsTotal(0); + return paginationResult; + } + int count = deviceDAO.getGroupedDevicesCount(request, devicesIds, groupName, tenantId); + paginationResult.setRecordsFiltered(count); + paginationResult.setRecordsTotal(count); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving device list for device ids " + devicesIds; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + paginationResult.setData(populateAllDeviceInfo(subscribedDeviceDetails)); + return paginationResult; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java index f729218314..c5e7417c86 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.service; @@ -60,10 +77,11 @@ public interface GroupManagementProviderService { * Delete existing device group. * * @param groupId to be deleted. + * @param isDeleteChildren to delete the children groups or not. * @return status of the delete operation. * @throws GroupManagementException */ - boolean deleteGroup(int groupId) throws GroupManagementException; + boolean deleteGroup(int groupId, boolean isDeleteChildren) throws GroupManagementException; /** * Get the device group provided the device group id. @@ -75,6 +93,17 @@ public interface GroupManagementProviderService { */ DeviceGroup getGroup(int groupId, boolean requireGroupProps) throws GroupManagementException; + /** + * Get the device group provided the device group id and depth of children groups. + * + * @param groupId of the group. + * @param requireGroupProps to include group properties. + * @param depth of children groups to retrieve. + * @return {@link DeviceGroup} group with details. + * @throws GroupManagementException on error during retrieval of group + */ + DeviceGroup getGroup(int groupId, boolean requireGroupProps, int depth) throws GroupManagementException; + /** * Get the device group provided the device group name. * @@ -85,6 +114,17 @@ public interface GroupManagementProviderService { */ DeviceGroup getGroup(String groupName, boolean requireGroupProps) throws GroupManagementException; + /** + * Get the device group provided the device group id and depth of children groups. + * + * @param groupName of the group. + * @param requireGroupProps to include group properties. + * @param depth of children groups to retrieve. + * @return {@link DeviceGroup} group with details. + * @throws GroupManagementException on error during retrieval of group + */ + DeviceGroup getGroup(String groupName, boolean requireGroupProps, int depth) throws GroupManagementException; + /** * Get all device groups in tenant. * @@ -127,6 +167,18 @@ public interface GroupManagementProviderService { PaginationResult getGroups(String username, GroupPaginationRequest paginationRequest, boolean requireGroupProps) throws GroupManagementException; + /** + * Get device groups with children groups hierarchically which belongs to specified user with pagination. + * + * @param username of the user. + * @param request to filter results + * @param requireGroupProps to include group properties + * @return {@link PaginationResult} paginated groups. + * @throws GroupManagementException on error during retrieval of groups with hierarchy + */ + PaginationResult getGroupsWithHierarchy(String username, GroupPaginationRequest request, + boolean requireGroupProps) throws GroupManagementException; + /** * Get all device group count in tenant * @@ -147,10 +199,11 @@ public interface GroupManagementProviderService { * Get device group count of user * * @param username of the user + * @param parentPath of the group * @return group count * @throws GroupManagementException */ - int getGroupCount(String username) throws GroupManagementException; + int getGroupCount(String username, String parentPath) throws GroupManagementException; /** * Manage device group sharing with user with list of roles. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java index b28cbefe25..6a678c1fca 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -14,10 +14,28 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.service; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; @@ -36,14 +54,12 @@ import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupNotExistException; import org.wso2.carbon.device.mgt.common.group.mgt.RoleDoesNotExistException; -import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GroupDAO; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; -import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration; import org.wso2.carbon.device.mgt.core.event.config.GroupAssignmentEventOperationExecutor; import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; @@ -56,10 +72,11 @@ import org.wso2.carbon.user.api.UserStoreManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.stream.Collectors; public class GroupManagementProviderServiceImpl implements GroupManagementProviderService { @@ -95,6 +112,20 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.beginTransaction(); DeviceGroup existingGroup = this.groupDAO.getGroup(deviceGroup.getName(), tenantId); if (existingGroup == null) { + if (deviceGroup.getParentGroupId() == 0) { + deviceGroup.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); + } else { + DeviceGroup immediateParentGroup = groupDAO.getGroup(deviceGroup.getParentGroupId(), tenantId); + if (immediateParentGroup == null) { + String msg = "Parent group with group ID '" + deviceGroup.getParentGroupId() + + "' does not exist. Hence creating of group '" + deviceGroup.getName() + + "' was not success"; + log.error(msg); + throw new GroupManagementException(msg); + } + String parentPath = DeviceManagerUtil.createParentPath(immediateParentGroup); + deviceGroup.setParentPath(parentPath); + } int updatedGroupID = this.groupDAO.addGroup(deviceGroup, tenantId); if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { this.groupDAO.addGroupProperties(deviceGroup, updatedGroupID, tenantId); @@ -146,7 +177,35 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.beginTransaction(); DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId); if (existingGroup != null) { - this.groupDAO.updateGroup(deviceGroup, groupId, tenantId); + List groupsToUpdate = new ArrayList<>(); + String immediateParentID = StringUtils.substringAfterLast(existingGroup.getParentPath(), DeviceGroupConstants.HierarchicalGroup.SEPERATOR); + String parentPath = ""; + if (deviceGroup.getParentGroupId() == 0) { + deviceGroup.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); + } else { + DeviceGroup immediateParentGroup = groupDAO.getGroup(deviceGroup.getParentGroupId(), tenantId); + if (immediateParentGroup == null) { + String msg = "Parent group with group ID '" + deviceGroup.getParentGroupId() + + "' does not exist. Hence updating of group '" + groupId + + "' was not success"; + log.error(msg); + throw new GroupManagementException(msg); + } + parentPath = DeviceManagerUtil.createParentPath(immediateParentGroup); + deviceGroup.setParentPath(parentPath); + } + deviceGroup.setGroupId(groupId); + groupsToUpdate.add(deviceGroup); + if (StringUtils.isNotBlank(immediateParentID)) { + List childrenGroups = groupDAO.getChildrenGroups( + DeviceManagerUtil.createParentPath(existingGroup), tenantId); + for (DeviceGroup childrenGroup : childrenGroups) { + childrenGroup.setParentPath(childrenGroup.getParentPath() + .replace(existingGroup.getParentPath(), parentPath)); + groupsToUpdate.add(childrenGroup); + } + } + this.groupDAO.updateGroups(groupsToUpdate, tenantId); if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { this.groupDAO.updateGroupProperties(deviceGroup, groupId, tenantId); } @@ -178,7 +237,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid * {@inheritDoc} */ @Override - public boolean deleteGroup(int groupId) throws GroupManagementException { + public boolean deleteGroup(int groupId, boolean isDeleteChildren) throws GroupManagementException { if (log.isDebugEnabled()) { log.debug("Delete group: " + groupId); } @@ -189,8 +248,37 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); try { GroupManagementDAOFactory.beginTransaction(); - this.groupDAO.deleteGroup(groupId, tenantId); - this.groupDAO.deleteAllGroupProperties(groupId, tenantId); + List childrenGroups = new ArrayList<>(); + List groupIdsToDelete = new ArrayList<>(); + if (deviceGroup.getChildrenGroups() != null && !deviceGroup.getChildrenGroups().isEmpty()) { + String parentPath = DeviceManagerUtil.createParentPath(deviceGroup); + childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + if (isDeleteChildren) { + groupIdsToDelete = childrenGroups.stream().map(DeviceGroup::getGroupId) + .collect(Collectors.toList()); + } else { + for (DeviceGroup childrenGroup : childrenGroups) { + String newParentPath = childrenGroup.getParentPath() + .replace(DeviceGroupConstants.HierarchicalGroup.SEPERATOR + deviceGroup.getGroupId(), ""); + if (StringUtils.isEmpty(newParentPath)) { + newParentPath = DeviceGroupConstants.HierarchicalGroup.SEPERATOR; + } + childrenGroup.setParentPath(newParentPath); + } + } + } + if (isDeleteChildren) { + groupIdsToDelete.add(groupId); + groupDAO.deleteGroupsMapping(groupIdsToDelete, tenantId); + groupDAO.deleteGroups(groupIdsToDelete, tenantId); + groupDAO.deleteAllGroupsProperties(groupIdsToDelete, tenantId); + } else { + groupDAO.deleteGroup(groupId, tenantId); + groupDAO.deleteAllGroupProperties(groupId, tenantId); + if (!childrenGroups.isEmpty()) { + groupDAO.updateGroups(childrenGroups, tenantId); + } + } GroupManagementDAOFactory.commitTransaction(); if (log.isDebugEnabled()) { log.debug("DeviceGroup " + deviceGroup.getName() + " removed."); @@ -219,6 +307,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid */ @Override public DeviceGroup getGroup(int groupId, boolean requireGroupProps) throws GroupManagementException { + return getGroup(groupId, requireGroupProps, 1); + } + + @Override + public DeviceGroup getGroup(int groupId, boolean requireGroupProps, int depth) throws GroupManagementException { if (log.isDebugEnabled()) { log.debug("Get group by id: " + groupId); } @@ -227,8 +320,13 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.openConnection(); deviceGroup = this.groupDAO.getGroup(groupId, tenantId); - if (requireGroupProps) { - populateGroupProperties(deviceGroup, tenantId); + if (deviceGroup != null) { + String parentPath = DeviceManagerUtil.createParentPath(deviceGroup); + List childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren(deviceGroup, childrenGroups, requireGroupProps, tenantId, depth, 0); + if (requireGroupProps) { + populateGroupProperties(deviceGroup, tenantId); + } } return deviceGroup; } catch (GroupManagementDAOException e) { @@ -236,11 +334,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.error(msg, e); throw new GroupManagementException(msg, e); } catch (SQLException e) { - String msg = "Error occurred while opening a connection to the data source."; - log.error(msg, e); - throw new GroupManagementException(msg, e); - } catch (Exception e) { - String msg = "Error occurred in getGroup for groupId: " + groupId; + String msg = "Error occurred while opening a connection to the data source to retrieve the group '" + + groupId + "'"; log.error(msg, e); throw new GroupManagementException(msg, e); } finally { @@ -253,6 +348,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid */ @Override public DeviceGroup getGroup(String groupName, boolean requireGroupProps) throws GroupManagementException { + return getGroup(groupName, requireGroupProps, 1); + } + + @Override + public DeviceGroup getGroup(String groupName, boolean requireGroupProps, int depth) throws GroupManagementException { if (groupName == null) { String msg = "Received empty groupName for getGroup"; log.error(msg); @@ -266,8 +366,13 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.openConnection(); deviceGroup = this.groupDAO.getGroup(groupName, tenantId); - if (requireGroupProps) { - populateGroupProperties(deviceGroup, tenantId); + if (deviceGroup != null) { + String parentPath = DeviceManagerUtil.createParentPath(deviceGroup); + List childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren(deviceGroup, childrenGroups, requireGroupProps, tenantId, depth , 0); + if (requireGroupProps) { + populateGroupProperties(deviceGroup, tenantId); + } } return deviceGroup; } catch (GroupManagementDAOException e) { @@ -275,11 +380,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.error(msg, e); throw new GroupManagementException(msg, e); } catch (SQLException e) { - String msg = "Error occurred while opening a connection to the data source."; - log.error(msg, e); - throw new GroupManagementException(msg, e); - } catch (Exception e) { - String msg = "Error occurred in getGroup with name " + groupName; + String msg = "Error occurred while opening a connection to the data source to retrieve group with name '" + + groupName + "'"; log.error(msg, e); throw new GroupManagementException(msg, e); } finally { @@ -296,12 +398,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - deviceGroups = this.groupDAO.getGroups(tenantId); - if (requireGroupProps) { - if (deviceGroups != null && !deviceGroups.isEmpty()) { - for (DeviceGroup group : deviceGroups) { - populateGroupProperties(group, tenantId); - } + deviceGroups = groupDAO.getRootGroups(tenantId); + for (DeviceGroup deviceGroup : deviceGroups) { + if (requireGroupProps) { + populateGroupProperties(deviceGroup, tenantId); } } return deviceGroups; @@ -334,16 +434,15 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.debug("Get groups with pagination " + request.toString()); } request = DeviceManagerUtil.validateGroupListPageSize(request); - List deviceGroups; + List rootGroups; try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - deviceGroups = this.groupDAO.getGroups(request, tenantId); - if (requireGroupProps) { - if (deviceGroups != null && !deviceGroups.isEmpty()) { - for (DeviceGroup group : deviceGroups) { - populateGroupProperties(group, tenantId); - } + request.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); + rootGroups = this.groupDAO.getGroups(request, tenantId); + for (DeviceGroup rootGroup : rootGroups) { + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); } } } catch (GroupManagementDAOException e) { @@ -362,11 +461,68 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.closeConnection(); } PaginationResult groupResult = new PaginationResult(); - groupResult.setData(deviceGroups); + groupResult.setData(rootGroups); groupResult.setRecordsTotal(getGroupCount(request)); return groupResult; } + @Override + public PaginationResult getGroupsWithHierarchy(String username, GroupPaginationRequest request, + boolean requireGroupProps) throws GroupManagementException { + if (request == null) { + String msg = "Received incomplete data for retrieve groups with hierarchy"; + log.error(msg); + throw new GroupManagementException(msg); + } + if (log.isDebugEnabled()) { + log.debug("Get groups with hierarchy " + request.toString()); + } + DeviceManagerUtil.validateGroupListPageSize(request); + List rootGroups; + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + request.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); + if (StringUtils.isBlank(username)) { + GroupManagementDAOFactory.openConnection(); + rootGroups = groupDAO.getGroups(request, tenantId); + } else { + List allDeviceGroupIdsOfUser = getGroupIds(username); + GroupManagementDAOFactory.openConnection(); + rootGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); + } + String parentPath; + List childrenGroups; + for (DeviceGroup rootGroup : rootGroups) { + parentPath = DeviceManagerUtil.createParentPath(rootGroup); + childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren( + rootGroup, childrenGroups, requireGroupProps, tenantId, request.getDepth(), 0); + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); + } + } + } catch (GroupManagementDAOException e) { + String msg = "Error occurred while retrieving all groups with hierarchy"; + log.error(msg, e); + throw new GroupManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source to retrieve all groups " + + "with hierarchy"; + log.error(msg, e); + throw new GroupManagementException(msg, e); + } finally { + GroupManagementDAOFactory.closeConnection(); + } + PaginationResult groupResult = new PaginationResult(); + groupResult.setData(rootGroups); + if (StringUtils.isBlank(username)) { + groupResult.setRecordsTotal(getGroupCount(request)); + } else { + groupResult.setRecordsTotal(getGroupCount(username, request.getParentPath())); + } + return groupResult; + } + @Override public List getGroups(String username, boolean requireGroupProps) throws GroupManagementException { if (username == null || username.isEmpty()) { @@ -457,16 +613,15 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } request = DeviceManagerUtil.validateGroupListPageSize(request); List allDeviceGroupIdsOfUser = getGroupIds(currentUser); - List allMatchingGroups; + List rootGroups; try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - allMatchingGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); - if (requireGroupProps) { - if (allMatchingGroups != null && !allMatchingGroups.isEmpty()) { - for (DeviceGroup group : allMatchingGroups) { - populateGroupProperties(group, tenantId); - } + request.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); + rootGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); + for (DeviceGroup rootGroup : rootGroups) { + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); } } } catch (GroupManagementDAOException | SQLException e) { @@ -481,8 +636,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.closeConnection(); } PaginationResult groupResult = new PaginationResult(); - groupResult.setData(allMatchingGroups); - groupResult.setRecordsTotal(getGroupCount(currentUser)); + groupResult.setData(rootGroups); + groupResult.setRecordsTotal(getGroupCount(currentUser, request.getParentPath())); return groupResult; } @@ -557,7 +712,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid * {@inheritDoc} */ @Override - public int getGroupCount(String username) throws GroupManagementException { + public int getGroupCount(String username, String parentPath) throws GroupManagementException { if (username == null || username.isEmpty()) { String msg = "Received empty user name for getGroupCount"; log.error(msg); @@ -574,8 +729,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid .getUserStoreManager(); String[] roleList = userStoreManager.getRoleListOfUser(username); GroupManagementDAOFactory.openConnection(); - count = groupDAO.getOwnGroupsCount(username, tenantId); - count += groupDAO.getGroupsCount(roleList, tenantId); + count = groupDAO.getOwnGroupsCount(username, tenantId, parentPath); + count += groupDAO.getGroupsCount(roleList, tenantId, parentPath); return count; } catch (UserStoreException e) { String msg = "Error occurred while retrieving role list of user '" + username + "'"; @@ -1131,4 +1286,40 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } } } + + /** + * Recursive method to create group with children based on params to provide hierarchical grouping. + * @param parentGroup to which children group should be set. + * @param childrenGroups which are descendants of parent group. + * @param requireGroupProps to include device properties. + * @param tenantId of the group. + * @param depth of children groups set and when reaches recursive call returns to callee. + * @param counter to track the recursive calls and to stop when reaches the depth. + * @throws GroupManagementDAOException on error during population of group properties. + */ + private void createGroupWithChildren(DeviceGroup parentGroup, List childrenGroups, + boolean requireGroupProps, int tenantId, int depth, int counter) throws GroupManagementDAOException { + if (childrenGroups.isEmpty() || depth == counter) { + return; + } + List immediateChildrenGroups = new ArrayList<>(); + Iterator iterator = childrenGroups.iterator(); + while (iterator.hasNext()) { + DeviceGroup childGroup = iterator.next(); + int immediateParentID = Integer.parseInt(StringUtils.substringAfterLast( + childGroup.getParentPath(), DeviceGroupConstants.HierarchicalGroup.SEPERATOR)); + if (immediateParentID == parentGroup.getGroupId()) { + if (requireGroupProps) { + populateGroupProperties(childGroup, tenantId); + } + immediateChildrenGroups.add(childGroup); + iterator.remove(); + } + } + parentGroup.setChildrenGroups(immediateChildrenGroups); + counter++; + for (DeviceGroup nextParentGroup : immediateChildrenGroups) { + createGroupWithChildren(nextParentGroup, childrenGroups, requireGroupProps, tenantId, depth, counter); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 7822754208..36315a1315 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -70,6 +70,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException; @@ -1162,4 +1163,18 @@ public final class DeviceManagerUtil { .getUserStoreManager(); return userStoreManager.getUserClaimValue(username, claimUri, null); } + + /** + * Create the parent path that the children groups can have + * @param deviceGroup parent group + * @return created parent path + */ + public static String createParentPath(DeviceGroup deviceGroup) { + if (DeviceGroupConstants.HierarchicalGroup.SEPERATOR.equals(deviceGroup.getParentPath())) { + return deviceGroup.getParentPath() + deviceGroup.getGroupId(); + } else { + return deviceGroup.getParentPath() + DeviceGroupConstants.HierarchicalGroup.SEPERATOR + + deviceGroup.getGroupId(); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/MDMAndroidOperationUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/MDMAndroidOperationUtil.java index 14dbaea9ed..99cacfd950 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/MDMAndroidOperationUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/MDMAndroidOperationUtil.java @@ -52,6 +52,7 @@ public class MDMAndroidOperationUtil { enterpriseApplication.setType(application.getType().toString()); enterpriseApplication.setUrl(application.getLocation()); enterpriseApplication.setAppIdentifier(application.getIdentifier()); + enterpriseApplication.setProperties(application.getProperties()); operation.setPayLoad(enterpriseApplication.toJSON()); break; case PUBLIC: @@ -59,6 +60,7 @@ public class MDMAndroidOperationUtil { new AppStoreApplication(); appStoreApplication.setType(application.getType().toString()); appStoreApplication.setAppIdentifier(application.getIdentifier()); + appStoreApplication.setProperties(application.getProperties()); operation.setPayLoad(appStoreApplication.toJSON()); break; case WEBAPP: @@ -67,6 +69,7 @@ public class MDMAndroidOperationUtil { webApplication.setUrl(application.getLocation()); webApplication.setName(application.getName()); webApplication.setType(application.getType().toString()); + webApplication.setProperties(application.getProperties()); operation.setPayLoad(webApplication.toJSON()); break; default: @@ -93,6 +96,7 @@ public class MDMAndroidOperationUtil { new EnterpriseApplication(); enterpriseApplication.setType(application.getType().toString()); enterpriseApplication.setAppIdentifier(application.getIdentifier()); + enterpriseApplication.setProperties(application.getProperties()); operation.setPayLoad(enterpriseApplication.toJSON()); break; case PUBLIC: diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java index fd34165031..ec8004e475 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java @@ -8,6 +8,23 @@ * * 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. + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 @@ -103,7 +120,7 @@ public class GroupManagementProviderServiceNegativeTest extends BaseDeviceManage expectedExceptions = {GroupManagementException.class}, expectedExceptionsMessageRegExp = "Error occurred " + "while retrieving group count of user.*") public void testGetGroupCountWithUserName() throws GroupManagementException { - groupManagementProviderService.getGroupCount("test"); + groupManagementProviderService.getGroupCount("test", null); } @@ -145,7 +162,7 @@ public class GroupManagementProviderServiceNegativeTest extends BaseDeviceManage expectedExceptions = {GroupManagementException.class}, expectedExceptionsMessageRegExp = "Received empty " + "user name for getGroupCount.*") public void testGetGroupCountWithUserName2() throws GroupManagementException { - groupManagementProviderService.getGroupCount(null); + groupManagementProviderService.getGroupCount(null, null); } @Test(description = "This method tests getGroups method under negative circumstances", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java index 4ffb675fe7..b645eac9a0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://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 org.wso2.carbon.device.mgt.core.service; @@ -119,13 +136,13 @@ public class GroupManagementProviderServiceTest extends BaseDeviceManagementTest @Test(dependsOnMethods = ("createGroup")) public void deleteGroup() throws GroupManagementException { DeviceGroup deviceGroup = groupManagementProviderService.getGroup(TestUtils.createDeviceGroup4().getName(), false); - Assert.assertTrue(groupManagementProviderService.deleteGroup(deviceGroup.getGroupId())); + Assert.assertTrue(groupManagementProviderService.deleteGroup(deviceGroup.getGroupId(), false)); } @Test(dependsOnMethods = ("createGroup")) public void deleteGroupNotExists() throws GroupManagementException { - groupManagementProviderService.deleteGroup(8); + groupManagementProviderService.deleteGroup(8, false); } @@ -190,7 +207,7 @@ public class GroupManagementProviderServiceTest extends BaseDeviceManagementTest @Test(dependsOnMethods = ("createGroup")) public void getGroupCountByUsername(String username) throws GroupManagementException { - int x = groupManagementProviderService.getGroupCount(username); + int x = groupManagementProviderService.getGroupCount(username, null); Assert.assertNotNull(x); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql index a380bf5204..2c846cb1af 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql @@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -398,7 +399,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_INFO ( DEVICE_ID INT NULL, ENROLMENT_ID INT NOT NULL, KEY_FIELD VARCHAR(45) NULL, - VALUE_FIELD VARCHAR(1000) NULL, + VALUE_FIELD VARCHAR(1500) NULL, PRIMARY KEY (ID), CONSTRAINT DM_DEVICE_INFO_DEVICE FOREIGN KEY (DEVICE_ID) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/resources/sql-files/h2.sql b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/resources/sql-files/h2.sql index eedbcd875a..7d7c1ece9c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/resources/sql-files/h2.sql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/resources/sql-files/h2.sql @@ -400,7 +400,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_INFO ( ID INTEGER AUTO_INCREMENT NOT NULL, DEVICE_ID INT NULL, KEY_FIELD VARCHAR(45) NULL, - VALUE_FIELD VARCHAR(1000) NULL, + VALUE_FIELD VARCHAR(1500) NULL, PRIMARY KEY (ID), CONSTRAINT DM_DEVICE_INFO_DEVICE FOREIGN KEY (DEVICE_ID) diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql index e53054a6a0..7238d37790 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql @@ -18,6 +18,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( DATE_OF_CREATE BIGINT DEFAULT NULL, DATE_OF_LAST_UPDATE BIGINT DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -452,7 +453,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_INFO ( DEVICE_ID INT NULL, ENROLMENT_ID INT NOT NULL, KEY_FIELD VARCHAR(45) NULL, - VALUE_FIELD VARCHAR(1000) NULL, + VALUE_FIELD VARCHAR(1500) NULL, PRIMARY KEY (ID), CONSTRAINT DM_DEVICE_INFO_DEVICE FOREIGN KEY (DEVICE_ID) @@ -607,4 +608,4 @@ DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID AND DM_DEVICE.ID = DM_DEVICE_DETAIL.DEVICE_ID ORDER BY TENANT_ID, DEVICE_ID; --- END OF DASHBOARD RELATED VIEWS -- \ No newline at end of file +-- END OF DASHBOARD RELATED VIEWS -- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 0fb5fc7c42..f6894eb4ac 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -424,7 +425,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_INFO ( DEVICE_ID INT NULL, ENROLMENT_ID INT NOT NULL, KEY_FIELD VARCHAR(45) NULL, - VALUE_FIELD VARCHAR(1000) NULL, + VALUE_FIELD VARCHAR(1500) NULL, PRIMARY KEY (ID), CONSTRAINT DM_DEVICE_INFO_DEVICE FOREIGN KEY (DEVICE_ID) @@ -722,4 +723,4 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); --- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index c70277074a..c27f891445 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -32,6 +32,7 @@ IF NOT EXISTS(SELECT * STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION VARCHAR(MAX) DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -474,7 +475,7 @@ CREATE TABLE DM_DEVICE_INFO ( DEVICE_ID INTEGER NULL, ENROLMENT_ID INTEGER NOT NULL, KEY_FIELD VARCHAR(45) NULL, - VALUE_FIELD VARCHAR(1000) NULL, + VALUE_FIELD VARCHAR(1500) NULL, PRIMARY KEY (ID), INDEX DM_DEVICE_INFO_DEVICE_idx (DEVICE_ID ASC), INDEX DM_DEVICE_INFO_DEVICE_ENROLLMENT_idx (ENROLMENT_ID ASC), @@ -714,4 +715,4 @@ CREATE TABLE DM_GEOFENCE ( PRIMARY KEY (ID) ); --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index 6ba30303b8..a69b79b783 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -27,6 +27,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ) @@ -491,7 +492,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_INFO ( DEVICE_ID INT NULL, ENROLMENT_ID INT NOT NULL, KEY_FIELD VARCHAR(45) NULL, - VALUE_FIELD VARCHAR(1000) NULL, + VALUE_FIELD VARCHAR(1500) NULL, PRIMARY KEY (ID), INDEX DM_DEVICE_INFO_DEVICE_idx (DEVICE_ID ASC), INDEX DM_DEVICE_INFO_DEVICE_ENROLLMENT_idx (ENROLMENT_ID ASC), @@ -786,4 +787,4 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB; --- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql index de19680e81..e2e4693bd2 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -50,6 +50,7 @@ CREATE TABLE DM_GROUP ( GROUP_NAME VARCHAR2(100) DEFAULT NULL, STATUS VARCHAR2(50) DEFAULT NULL, OWNER VARCHAR2(255) DEFAULT NULL, + PARENT_PATH VARCHAR2(255) DEFAULT NULL, TENANT_ID NUMBER(10) DEFAULT 0, CONSTRAINT PK_DM_GROUP PRIMARY KEY (ID) ) @@ -779,7 +780,7 @@ CREATE TABLE DM_DEVICE_INFO ( DEVICE_ID NUMBER(10) NOT NULL, ENROLMENT_ID NUMBER(10) NOT NULL, KEY_FIELD VARCHAR2(45) NULL, - VALUE_FIELD VARCHAR2(1000) NULL, + VALUE_FIELD VARCHAR2(1500) NULL, PRIMARY KEY (ID), CONSTRAINT DM_DEVICE_INFO_DEVICE FOREIGN KEY (DEVICE_ID) @@ -1083,4 +1084,4 @@ CREATE TABLE DM_GEOFENCE ( CONSTRAINT PK_DM_GEOFENCE PRIMARY KEY (ID) ); --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql index db431497e8..bd8eb8771a 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( GROUP_NAME VARCHAR(100) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ) @@ -732,4 +733,4 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE ( PRIMARY KEY (ID) ); --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE--