diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java index b909ff609b1..93edca0451e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java @@ -18,18 +18,11 @@ */ package org.wso2.carbon.device.mgt.jaxrs.service.api.admin; -import io.swagger.annotations.SwaggerDefinition; -import io.swagger.annotations.Info; -import io.swagger.annotations.ExtensionProperty; -import io.swagger.annotations.Extension; -import io.swagger.annotations.Tag; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.*; +import org.apache.axis2.transport.http.HTTPConstants; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scopes; +import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.PasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -61,6 +54,12 @@ import javax.ws.rs.core.Response; description = "View Users", key = "perm:admin-users:view", permissions = {"/device-mgt/users/manage"} + ), + @Scope( + name = "Delete Users Device Information", + description = "Delete users device details", + key = "perm:admin-users:remove", + permissions = {"/device-mgt/users/manage"} ) } ) @@ -127,4 +126,131 @@ public interface UserManagementAdminService { value = "Credential.", required = true) PasswordResetWrapper credentials); + + + @Path("/{username}/devices") + @DELETE + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_DELETE, + value = "Delete a users associated devices.", + notes = "If you wish to remove an device details to comply with the privacy requirements, can be done with " + + "this resource.", + tags = "Device details remove", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin-users:remove") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Users devices and details has been deleted successfully.", + 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 = 404, + message = "Group not found.", + response = ErrorResponse.class), + @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 removing the group.", + response = ErrorResponse.class) + }) + Response deleteDeviceOfUser(@ApiParam( + name = "username", + value = "Username of the users devices to be deleted.", + required = true) + @PathParam("username") String username); + + + + //device remove request would looks like follows + //DELETE devices/type/virtual_firealarm/id/us06ww93auzp + @DELETE + @Path("/type/{device-type}/id/{device-id}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + consumes = MediaType.APPLICATION_JSON, + httpMethod = "DELETE", + value = "Remove the information of device specified by device id", + notes = "Returns the status of the deleted device information.", + tags = "Device details remove privacy compliance", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin-users:remove") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully deleted the device information.", + response = Device.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. Empty body because the client already has the latest " + + "version of the requested resource."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n No device is found under the provided type and id.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving information requested device.", + response = ErrorResponse.class) + }) + Response deleteDevice( + @ApiParam( + name = "device-type", + value = "The device type, such as ios, android or windows.", + required = true) + @PathParam("device-type") + @Size(max = 45) + String deviceType, + @ApiParam( + name = "device-id", + value = "The device identifier of the device.", + required = true) + @PathParam("device-id") + @Size(max = 45) + String deviceId); + + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java index d268eff2826..d695619b0b0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java @@ -18,9 +18,17 @@ */ package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin; +import io.swagger.annotations.ApiParam; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.netbeans.lib.cvsclient.commandLine.command.log; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.PrivacyComplianceException; import org.wso2.carbon.device.mgt.jaxrs.beans.PasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.UserManagementAdminService; import org.wso2.carbon.device.mgt.jaxrs.util.CredentialManagementResponseBuilder; +import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import javax.validation.constraints.Size; import javax.ws.rs.*; @@ -32,16 +40,45 @@ import javax.ws.rs.core.Response; @Consumes(MediaType.APPLICATION_JSON) public class UserManagementAdminServiceImpl implements UserManagementAdminService { + private static final Log log = LogFactory.getLog(UserManagementAdminServiceImpl.class); + @POST @Path("/{username}/credentials") @Override public Response resetUserPassword(@PathParam("username") @Size(max = 45) - String user, @QueryParam("domain") String domain, PasswordResetWrapper credentials) { + String user, @QueryParam("domain") String domain, PasswordResetWrapper credentials) { if (domain != null && !domain.isEmpty()) { user = domain + '/' + user; } return CredentialManagementResponseBuilder.buildResetPasswordResponse(user, credentials); } + @Override + public Response deleteDeviceOfUser(@PathParam("username") String username) { + try { + DeviceMgtAPIUtils.getPrivacyComplianceProvider().deleteDevicesOfUser(username); + return Response.status(Response.Status.OK).build(); + } catch (PrivacyComplianceException e) { + String msg = "Error occurred while deleting the devices belongs to the user."; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @Override + public Response deleteDevice(@PathParam("device-type") @Size(max = 45) String deviceType, + @PathParam("device-id") @Size(max = 45) String deviceId) { + + try { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId, deviceType); + DeviceMgtAPIUtils.getPrivacyComplianceProvider().deleteDeviceDetails(deviceIdentifier); + return Response.status(Response.Status.OK).build(); + } catch (PrivacyComplianceException e) { + String msg = "Error occurred while deleting the devices information."; + 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/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index 02f8ce62a97..a795fca1a54 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -49,6 +49,7 @@ import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagement import org.wso2.carbon.device.mgt.common.spi.DeviceTypeGeneratorService; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; +import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; @@ -297,6 +298,19 @@ public class DeviceMgtAPIUtils { return realmService; } + public static PrivacyComplianceProvider getPrivacyComplianceProvider() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + PrivacyComplianceProvider privacyComplianceProvider = + (PrivacyComplianceProvider) ctx.getOSGiService(PrivacyComplianceProvider.class, null); + if (privacyComplianceProvider == null) { + String msg = "PrivacyComplianceProvider service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return privacyComplianceProvider; + } + + public static IntegrationClientService getIntegrationClientService() { if (integrationClientService == null) { synchronized (DeviceMgtAPIUtils.class) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PrivacyComplianceException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PrivacyComplianceException.java new file mode 100644 index 00000000000..a9bf316de0c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PrivacyComplianceException.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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; + +public class PrivacyComplianceException extends Exception { + + private static final long serialVersionUID = -3127931192903344297L; + + public PrivacyComplianceException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public PrivacyComplianceException(String message, Throwable cause) { + super(message, cause); + } + + public PrivacyComplianceException(String msg) { + super(msg); + } + + public PrivacyComplianceException() { + super(); + } + + public PrivacyComplianceException(Throwable cause) { + super(cause); + } + +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java index bd0d7cc86a2..9a76db22ac6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -39,6 +39,8 @@ import org.wso2.carbon.device.mgt.core.dao.impl.device.SQLServerDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsDAO; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.impl.DeviceDetailsDAOImpl; +import org.wso2.carbon.device.mgt.core.privacy.dao.PrivacyComplianceDAO; +import org.wso2.carbon.device.mgt.core.privacy.dao.impl.PrivacyComplianceDAOImpl; import javax.sql.DataSource; import java.sql.Connection; @@ -151,6 +153,10 @@ public class DeviceManagementDAOFactory { return new DeviceDetailsDAOImpl(); } + public static PrivacyComplianceDAO getPrivacyComplianceDAO() { + return new PrivacyComplianceDAOImpl(); + } + public static void init(DataSourceConfig config) { dataSource = resolveDataSource(config); try { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java index f6a3a3fc83e..4f8cd365aba 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java @@ -29,6 +29,7 @@ import org.wso2.carbon.device.mgt.core.app.mgt.config.AppManagementConfig; import org.wso2.carbon.device.mgt.core.config.license.LicenseConfig; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeServiceIdentifier; +import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; @@ -67,6 +68,7 @@ public class DeviceManagementDataHolder { private DeviceTaskManagerService deviceTaskManagerService; private DeviceStatusTaskManagerService deviceStatusTaskManagerService; private DeviceTypeGeneratorService deviceTypeGeneratorService; + private PrivacyComplianceProvider privacyComplianceProvider; private Map deviceStatusTaskPluginConfigs = Collections.synchronizedMap( new HashMap()); @@ -266,4 +268,12 @@ public class DeviceManagementDataHolder { DeviceTypeGeneratorService deviceTypeGeneratorService) { this.deviceTypeGeneratorService = deviceTypeGeneratorService; } + + public PrivacyComplianceProvider getPrivacyComplianceProvider() { + return privacyComplianceProvider; + } + + public void setPrivacyComplianceProvider(PrivacyComplianceProvider privacyComplianceProvider) { + this.privacyComplianceProvider = privacyComplianceProvider; + } } \ 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/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java index 47d709ac4ee..65decec77f1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -51,6 +51,8 @@ import org.wso2.carbon.device.mgt.core.notification.mgt.dao.NotificationManageme import org.wso2.carbon.device.mgt.core.operation.mgt.OperationManagerImpl; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; +import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; +import org.wso2.carbon.device.mgt.core.privacy.impl.PrivacyComplianceProviderImpl; import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository; import org.wso2.carbon.device.mgt.core.push.notification.mgt.task.PushNotificationSchedulerTask; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; @@ -225,6 +227,12 @@ public class DeviceManagementServiceComponent { .getPushNotificationConfiguration().getSchedulerTaskInitialDelay(), config .getPushNotificationConfiguration().getSchedulerBatchDelayMills(), TimeUnit.MILLISECONDS); } + + PrivacyComplianceProvider privacyComplianceProvider = new PrivacyComplianceProviderImpl(); + DeviceManagementDataHolder.getInstance().setPrivacyComplianceProvider(privacyComplianceProvider); + componentContext.getBundleContext().registerService(PrivacyComplianceProvider.class.getName(), + privacyComplianceProvider, null); + if (log.isDebugEnabled()) { log.debug("Device management core bundle has been successfully initialized"); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/PrivacyComplianceProvider.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/PrivacyComplianceProvider.java index 2d12ef58c1e..e661dbb212b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/PrivacyComplianceProvider.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/PrivacyComplianceProvider.java @@ -28,7 +28,5 @@ public interface PrivacyComplianceProvider { void deleteDeviceDetails(DeviceIdentifier deviceIdentifier) throws PrivacyComplianceException; - void deleteArchivedDataOfDevice(DeviceIdentifier deviceIdentifier) throws PrivacyComplianceException; - } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/PrivacyComplianceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/PrivacyComplianceDAO.java new file mode 100644 index 00000000000..d1b3862743b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/PrivacyComplianceDAO.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.privacy.dao; + +import org.wso2.carbon.device.mgt.core.privacy.impl.DeviceEnrollmentMapping; + +import java.util.List; + +public interface PrivacyComplianceDAO { + + List getDevicesOfUser(String username, int tenantId) throws PrivacyComplianceDAOException; + + void deleteDevice(int deviceId, int tenantId) throws PrivacyComplianceDAOException; + + void deleteDeviceEnrollments(int deviceId, int tenantId) throws PrivacyComplianceDAOException; + + void deleteDeviceEnrollments(int deviceId, int enrolmentId, int tenantId) throws PrivacyComplianceDAOException; + + void deleteDeviceDetails(int deviceId, int enrolmentId) throws PrivacyComplianceDAOException; + + void deleteDeviceApplications(int deviceId, int enrolmentId, int tenantId) throws PrivacyComplianceDAOException; + + void deleteDeviceProperties(int deviceId, int enrolmentId, int tenantId) throws PrivacyComplianceDAOException; + + void deleteDeviceLocation(int deviceId, int enrolmentId) throws PrivacyComplianceDAOException; + + void updateDeviceOperationResponses(int enrolmentId) throws PrivacyComplianceDAOException; + + void deleteDeviceOperationDetails(int enrolmentId) throws PrivacyComplianceDAOException; + + void deleteOperationEnrolmentMappings(int enrolmentId) throws PrivacyComplianceDAOException; + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/PrivacyComplianceDAOException.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/PrivacyComplianceDAOException.java new file mode 100644 index 00000000000..152a696b7b4 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/PrivacyComplianceDAOException.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.privacy.dao; + +public class PrivacyComplianceDAOException extends Exception { + + private static final long serialVersionUID = -3127931192903344297L; + + public PrivacyComplianceDAOException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public PrivacyComplianceDAOException(String message, Throwable cause) { + super(message, cause); + } + + public PrivacyComplianceDAOException(String msg) { + super(msg); + } + + public PrivacyComplianceDAOException() { + super(); + } + + public PrivacyComplianceDAOException(Throwable cause) { + super(cause); + } +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/impl/PrivacyComplianceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/impl/PrivacyComplianceDAOImpl.java new file mode 100644 index 00000000000..7c2b7d25b98 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/dao/impl/PrivacyComplianceDAOImpl.java @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.privacy.dao.impl; + +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import org.wso2.carbon.device.mgt.core.privacy.dao.PrivacyComplianceDAO; +import org.wso2.carbon.device.mgt.core.privacy.dao.PrivacyComplianceDAOException; +import org.wso2.carbon.device.mgt.core.privacy.impl.DeviceEnrollmentMapping; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class PrivacyComplianceDAOImpl implements PrivacyComplianceDAO { + + @Override + public List getDevicesOfUser(String username, int tenantId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + List deviceIds = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT * FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ? ORDER BY DEVICE_ID"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, username); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + + while (rs.next()) { + DeviceEnrollmentMapping mapping = new DeviceEnrollmentMapping(); + mapping.setDeviceId(rs.getInt("DEVICE_ID")); + mapping.setEnrolmentId(rs.getInt("ENROLMENT_ID")); + deviceIds.add(mapping); + } + if (deviceIds.isEmpty()) { + return null; + } + return deviceIds; + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while retrieving device ids " + + "related to the given user.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public void deleteDevice(int deviceId, int tenantId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the devices", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteDeviceEnrollments(int deviceId, int tenantId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device enrolments", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteDeviceEnrollments(int deviceId, int enrolmentId, int tenantId) + throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND TENANT_ID = ? AND ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + stmt.setInt(3, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device enrolments", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteDeviceDetails(int deviceId, int enrolmentId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_DETAIL WHERE DEVICE_ID = ? AND ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device details.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteDeviceApplications(int deviceId, int enrolmentId, int tenantId) + throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_APPLICATION_MAPPING WHERE DEVICE_ID = ? " + + "AND ENROLMENT_ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, enrolmentId); + stmt.setInt(3, tenantId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device applications.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteDeviceProperties(int deviceId, int enrolmentId, int tenantId) + throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_INFO WHERE DEVICE_ID = ? AND ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device information.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteDeviceLocation(int deviceId, int enrolmentId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_LOCATION WHERE DEVICE_ID = ? AND ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device location.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void updateDeviceOperationResponses(int enrolmentId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_DEVICE_OPERATION_RESPONSE SET OPERATION_RESPONSE = ? WHERE ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setNull(1, java.sql.Types.BLOB); + stmt.setInt(2, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device information.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + + @Override + public void deleteDeviceOperationDetails(int enrolmentId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_DEVICE_OPERATION_RESPONSE WHERE ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device information.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public void deleteOperationEnrolmentMappings(int enrolmentId) throws PrivacyComplianceDAOException { + + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT_OP_MAPPING WHERE ENROLMENT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + stmt.executeUpdate(); + + } catch (SQLException e) { + throw new PrivacyComplianceDAOException("Error occurred while deleting the device information.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + } + + 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/privacy/impl/DeviceEnrollmentMapping.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/impl/DeviceEnrollmentMapping.java new file mode 100644 index 00000000000..1acd1aa46e0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/impl/DeviceEnrollmentMapping.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.privacy.impl; + +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; + +public class DeviceEnrollmentMapping { + + private int deviceId; + private int enrolmentId; + private DeviceIdentifier deviceIdentifier; + private int tenantId; + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getEnrolmentId() { + return enrolmentId; + } + + public void setEnrolmentId(int enrolmentId) { + this.enrolmentId = enrolmentId; + } + + public DeviceIdentifier getDeviceIdentifier() { + return deviceIdentifier; + } + + public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) { + this.deviceIdentifier = deviceIdentifier; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/impl/PrivacyComplianceProviderImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/impl/PrivacyComplianceProviderImpl.java new file mode 100644 index 00000000000..072bf19c171 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/privacy/impl/PrivacyComplianceProviderImpl.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.privacy.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.PrivacyComplianceException; +import org.wso2.carbon.device.mgt.common.TransactionManagementException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; +import org.wso2.carbon.device.mgt.core.privacy.dao.PrivacyComplianceDAO; +import org.wso2.carbon.device.mgt.core.privacy.dao.PrivacyComplianceDAOException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PrivacyComplianceProviderImpl implements PrivacyComplianceProvider { + + private static final Log log = LogFactory.getLog(PrivacyComplianceProviderImpl.class); + + PrivacyComplianceDAO complianceDAO; + + public PrivacyComplianceProviderImpl() { + complianceDAO = DeviceManagementDAOFactory.getPrivacyComplianceDAO(); + } + + @Override + public void deleteDevicesOfUser(String username) throws PrivacyComplianceException { + + if (log.isDebugEnabled()) { + log.debug("Deleting the requested users."); + } + try { + DeviceManagementDAOFactory.beginTransaction(); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + List enrollmentMappings = complianceDAO.getDevicesOfUser(username, tenantId); + Map> deviceMap = new HashMap<>(); + int x = -1; + for (DeviceEnrollmentMapping m : enrollmentMappings) { + if (m.getDeviceId() != x) { + x = m.getDeviceId(); + List enrolments = new ArrayList<>(); + enrolments.add(m.getEnrolmentId()); + deviceMap.put(m.getDeviceId(), enrolments); + } else { + deviceMap.get(m.getDeviceId()).add(m.getEnrolmentId()); + } + } + for (int deviceId : deviceMap.keySet()) { + List enrollmentIds = deviceMap.get(deviceId); + for (Integer enrolmentId : enrollmentIds) { + complianceDAO.deleteDeviceOperationDetails(enrolmentId); + complianceDAO.deleteOperationEnrolmentMappings(enrolmentId); + complianceDAO.deleteDeviceApplications(deviceId, enrolmentId, tenantId); + complianceDAO.deleteDeviceDetails(deviceId, enrolmentId); + complianceDAO.deleteDeviceProperties(deviceId, enrolmentId, tenantId); + complianceDAO.deleteDeviceLocation(deviceId, enrolmentId); + complianceDAO.deleteDeviceEnrollments(deviceId, enrolmentId); + } + complianceDAO.deleteDevice(deviceId, tenantId); + } + DeviceManagementDAOFactory.commitTransaction(); + } catch (PrivacyComplianceDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting the devices and details of the given user"; + log.error(msg, e); + throw new PrivacyComplianceException(msg, e); + } catch (TransactionManagementException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Database error occurred while deleting the devices and details of the given user"; + log.error(msg, e); + throw new PrivacyComplianceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + log.info("Requested users device has been successfully removed..!"); + } + + @Override + public void deleteDeviceDetails(DeviceIdentifier deviceIdentifier) throws PrivacyComplianceException { + + if (log.isDebugEnabled()) { + log.debug("Deleting the requested device details."); + } + try { + Device device = this.getDevice(deviceIdentifier); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.beginTransaction(); + complianceDAO.deleteDeviceOperationDetails(device.getEnrolmentInfo().getId()); + complianceDAO.deleteOperationEnrolmentMappings(device.getEnrolmentInfo().getId()); + complianceDAO.deleteDeviceApplications(device.getId(), device.getEnrolmentInfo().getId(), tenantId); + complianceDAO.deleteDeviceDetails(device.getId(), device.getEnrolmentInfo().getId()); + complianceDAO.deleteDeviceProperties(device.getId(), device.getEnrolmentInfo().getId(), tenantId); + complianceDAO.deleteDeviceLocation(device.getId(), device.getEnrolmentInfo().getId()); + DeviceManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Database error occurred while deleting the device details."; + log.error(msg, e); + throw new PrivacyComplianceException(msg, e); + } catch (PrivacyComplianceDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting the device details."; + log.error(msg, e); + throw new PrivacyComplianceException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + + + } + + private Device getDevice(DeviceIdentifier deviceId) throws PrivacyComplianceException { + try { + return DeviceManagementDataHolder.getInstance().getDeviceManagementProvider().getDevice(deviceId, false); + } catch (DeviceManagementException e) { + throw new PrivacyComplianceException( + "Error occurred while retrieving device info.", e); + } + } +} +