diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2e6839b906..f22bfc39ca 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,13 @@ -image: shinyay/docker-mvn-jdk8:3.5.0 +image: charithag/docker-mvn-jdk8:latest variables: - MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode --errors --show-version" + MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode" MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" cache: paths: - .m2/repository/ + - target/ build: stage: build @@ -23,4 +24,4 @@ deploy: script: - mvn $MAVEN_CLI_OPTS deploy -Dmaven.test.skip=true only: - - master + - master@entgra/carbon-device-mgt diff --git a/README.md b/README.md index a9d61eaa2a..0da219f7a4 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,11 @@ [![pipeline status](https://gitlab.com/entgra/carbon-device-mgt/badges/master/pipeline.svg)](https://gitlab.com/entgra/carbon-device-mgt/commits/master) -WSO2 CONNECTED DEVICE MANAGEMENT COMPONENTS +Entgra CONNECTED DEVICE MANAGEMENT COMPONENTS -WSO2 Connected Device Manager (WSO2 CDM) is a comprehensive platform that helps solve mobile computing challenges enterprises face today when dealing with both corporate owned, personally enabled (COPE) devices and employee owned devices as part of a bring your own device (BYOD) program. +Entgra Connected Device Manager (Entgra CDM) is a comprehensive platform that helps solve mobile computing challenges +enterprises face today when dealing with both corporate owned, personally enabled (COPE) devices and employee owned devices as part of a bring your own device (BYOD) program. -Whether it is device provisioning, device configuration management, policy enforcement, mobile application management, device data security, or compliance monitoring, WSO2 CDM offers a single enterprise-grade platform to develop extensions for IOT related device types. +Whether it is device provisioning, device configuration management, policy enforcement, mobile application +management, device data security, or compliance monitoring, Entgra CDM offers a single enterprise-grade platform to +develop extensions for IOT related device types. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/Credential.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/Credential.java new file mode 100644 index 0000000000..f307f2184a --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/Credential.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.device.mgt.jaxrs.beans; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpStatus; +import org.apache.http.util.TextUtils; +import org.wso2.carbon.device.mgt.jaxrs.exception.BadRequestException; + +public class Credential { + + private static final Log log = LogFactory.getLog(Credential.class); + + private String username; + private String password; + private String tenantDomain; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getTenantDomain() { + return tenantDomain; + } + + public void setTenantDomain(String tenantDomain) { + this.tenantDomain = tenantDomain; + } + + public void validateRequest() { + if (TextUtils.isEmpty(getUsername())) { + String msg = "Error occurred while validating the user. Username is not found to validate the user"; + log.error(msg); + throw new BadRequestException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg) + .build()); + } + if (TextUtils.isEmpty(getPassword())) { + String msg = "Error occurred while validating the user. Password is not found to validate the user"; + log.error(msg); + throw new BadRequestException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(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/DeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java index c3519e423e..64815672f2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java @@ -60,6 +60,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.util.List; /** * Device related REST-API. This can be used to manipulated device related details. @@ -1452,5 +1453,198 @@ public interface DeviceManagementService { @ApiParam(name = "deviceOperation", value = "Operation object with device ids.", required = true) @Valid OperationRequest operationRequest); + @GET + @Path("/status/count/{type}/{status}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Get Device Count with status", + notes = "Get specified device count with status.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:details") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the details of the device.", + response = int.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 was last modified.\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.\n"), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n A device with the specified device type and id was not found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving the device details.", + response = ErrorResponse.class) + }) + Response getDeviceCountByStatus( + @ApiParam( + name = "type", + value = "The device type name, such as ios, android, windows or fire-alarm.", + required = true) + @PathParam("type") + @Size(max = 45) + String type, + @ApiParam( + name = "status", + value = "The device identifier of the device you want ot get details.", + required = true) + @PathParam("status") + @Size(max = 45) + String status); + + + @GET + @Path("/status/ids/{type}/{status}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Details of a Device", + notes = "Get the details of a device by specifying the device type and device identifier and optionally " + + "the owner.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:details") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the details of the device.", + response = String[].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 was last modified.\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.\n"), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n A device with the specified device type and id was not found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving the device details.", + response = ErrorResponse.class) + }) + Response getDeviceIdentifiersByStatus( + @ApiParam( + name = "type", + value = "The device type name, such as ios, android, windows or fire-alarm.", + required = true) + @PathParam("type") + @Size(max = 45) + String type, + @ApiParam( + name = "status", + value = "The device identifier of the device you want ot get details.", + required = true) + @PathParam("status") + @Size(max = 45) + String status); + @PUT + @Path("/status/update/{type}/{status}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + consumes = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "Changing the Status of a Devices", + notes = "Change the status of a devices from one state to another.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:change-status") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully changed the device status.", + 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 bulkUpdateDeviceStatus(@ApiParam(name = "type", value = "The device type, such as ios, android or windows.", required = true) + @PathParam("type") String type, + @ApiParam(name = "status", value = "The device type, such as ios, android or windows.", required = true) + @PathParam("status") String status, + @ApiParam(name = "deviceList", value = "The payload containing the new name of the device.", required = true) + @Valid List deviceList); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java index 12630fcd68..659276becb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.api; @@ -24,8 +40,6 @@ import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.Extension; import io.swagger.annotations.Tag; import io.swagger.annotations.Api; -import io.swagger.annotations.AuthorizationScope; -import io.swagger.annotations.Authorization; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; @@ -36,6 +50,7 @@ import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; +import org.wso2.carbon.device.mgt.jaxrs.beans.Credential; import org.wso2.carbon.device.mgt.jaxrs.beans.EnrollmentInvitation; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; @@ -905,4 +920,8 @@ public interface UserManagementService { value = "List of email address of recipients", required = true) @Valid EnrollmentInvitation enrollmentInvitation); + + @POST + @Path("/validate") + Response validateUser(Credential credential); } 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 1d17ac9450..10aa8538fa 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 @@ -788,4 +788,52 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } + + @GET + @Override + @Path("/status/count/{type}/{status}") + public Response getDeviceCountByStatus(@PathParam("type") String type, @PathParam("status") String status) { + int deviceCount; + try { + deviceCount = DeviceMgtAPIUtils.getDeviceManagementService().getDeviceCountOfTypeByStatus(type, status); + return Response.status(Response.Status.OK).entity(deviceCount).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Error while retrieving device count."; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build(); + } + } + + @GET + @Override + @Path("/status/ids/{type}/{status}") + public Response getDeviceIdentifiersByStatus(@PathParam("type") String type, @PathParam("status") String status) { + List deviceIds; + try { + deviceIds = DeviceMgtAPIUtils.getDeviceManagementService().getDeviceIdentifiersByStatus(type, status); + return Response.status(Response.Status.OK).entity(deviceIds.toArray(new String[0])).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Error while obtaining list of devices"; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build(); + } + } + + @PUT + @Override + @Path("/status/update/{type}/{status}") + public Response bulkUpdateDeviceStatus(@PathParam("type") String type, @PathParam("status") String status, + @Valid List deviceList) { + try { + DeviceMgtAPIUtils.getDeviceManagementService().bulkUpdateDeviceStatus(type, deviceList, status); + } catch (DeviceManagementException e) { + String errorMessage = "Error while updating device status in bulk."; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build(); + } + return Response.status(Response.Status.OK).build(); + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java index c31bc3b523..dae2bbbf53 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java @@ -15,12 +15,29 @@ * specific language governing permissions and limitations * under the License. * + * Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.impl; +import com.google.gson.JsonObject; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpStatus; import org.eclipse.wst.common.uriresolver.internal.util.URIEncoder; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; @@ -31,11 +48,13 @@ import org.wso2.carbon.device.mgt.core.service.EmailMetaInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.Credential; import org.wso2.carbon.device.mgt.jaxrs.beans.EnrollmentInvitation; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.RoleList; import org.wso2.carbon.device.mgt.jaxrs.beans.UserInfo; +import org.wso2.carbon.device.mgt.jaxrs.exception.BadRequestException; import org.wso2.carbon.device.mgt.jaxrs.service.api.UserManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -45,9 +64,12 @@ import org.wso2.carbon.identity.user.store.count.UserStoreCountRetriever; import org.wso2.carbon.identity.user.store.count.exception.UserStoreCounterException; import org.wso2.carbon.user.api.Permission; import org.wso2.carbon.user.api.RealmConfiguration; +import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; +import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.CarbonUtils; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -738,6 +760,44 @@ public class UserManagementServiceImpl implements UserManagementService { return Response.status(Response.Status.OK).entity("Invitation mails have been sent.").build(); } + @POST + @Path("/validate") + @Override + public Response validateUser(Credential credential) { + try { + credential.validateRequest(); + RealmService realmService = DeviceMgtAPIUtils.getRealmService(); + String tenant = credential.getTenantDomain(); + int tenantId; + if (tenant == null || tenant.trim().isEmpty()) { + tenantId = MultitenantConstants.SUPER_TENANT_ID; + } else { + tenantId = realmService.getTenantManager().getTenantId(tenant); + } + if (tenantId == MultitenantConstants.INVALID_TENANT_ID) { + String msg = "Error occurred while validating the user. Invalid tenant domain " + tenant; + log.error(msg); + throw new BadRequestException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg) + .build()); + } + UserRealm userRealm = realmService.getTenantUserRealm(tenantId); + JsonObject result = new JsonObject(); + if (userRealm.getUserStoreManager().authenticate(credential.getUsername(), credential.getPassword())) { + result.addProperty("valid", true); + return Response.status(Response.Status.OK).entity(result).build(); + } else { + result.addProperty("valid", false); + return Response.status(Response.Status.OK).entity(result).build(); + } + } catch (UserStoreException e) { + String msg = "Error occurred while retrieving user store to validate user"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + private Map buildDefaultUserClaims(String firstName, String lastName, String emailAddress) { Map defaultUserClaims = new HashMap<>(); defaultUserClaims.put(Constants.USER_CLAIM_FIRST_NAME, firstName); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml index b23f60be4c..fffbfbdb24 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml @@ -45,6 +45,13 @@ true + + nonSecuredEndPoints + + /api/device-mgt/v1.0/users/validate + + + managed-api-enabled diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceEnrollmentInfoNotification.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceEnrollmentInfoNotification.java new file mode 100644 index 0000000000..2d2e846c1f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceEnrollmentInfoNotification.java @@ -0,0 +1,82 @@ +/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common; + +public class DeviceEnrollmentInfoNotification { + + /*** + * Enrollment timestamp + */ + private Long dateOfEnrolment; + /*** + * Last updated timestamp + */ + private Long dateOfLastUpdate; + /*** + * Ownership of the device + */ + private String ownership; + /*** + * Status of the device + */ + private String status; + /*** + * Owner of the device + */ + private String owner; + + public Long getDateOfEnrolment() { + return dateOfEnrolment; + } + + public void setDateOfEnrolment(Long dateOfEnrolment) { + this.dateOfEnrolment = dateOfEnrolment; + } + + public Long getDateOfLastUpdate() { + return dateOfLastUpdate; + } + + public void setDateOfLastUpdate(Long dateOfLastUpdate) { + this.dateOfLastUpdate = dateOfLastUpdate; + } + + public String getOwnership() { + return ownership; + } + + public void setOwnership(String ownership) { + this.ownership = ownership; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceNotification.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceNotification.java new file mode 100644 index 0000000000..d376344939 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceNotification.java @@ -0,0 +1,53 @@ +/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "device") +public class DeviceNotification { + + + @XmlAttribute(name = "id") + private String identifier; + @XmlElement(name = "name") + private String deviceName; + @XmlElement(name = "type") + private String deviceType; + @XmlElement(name = "description") + private String description; + @XmlElement(name = "properties") + private DevicePropertyNotification properties; + @XmlElement(name = "enrollment_info") + private DeviceEnrollmentInfoNotification enrollmentInfo; + + public DeviceNotification(){} + + public DeviceNotification(String identifier, String deviceName, String deviceType, String description, + DevicePropertyNotification devicePropertyNotification, + DeviceEnrollmentInfoNotification deviceEnrollmentInfoNotification) { + this.identifier = identifier; + this.deviceName = deviceName; + this.deviceType = deviceType; + this.description = description; + this.properties = devicePropertyNotification; + this.enrollmentInfo = deviceEnrollmentInfoNotification; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DevicePropertyNotification.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DevicePropertyNotification.java new file mode 100644 index 0000000000..8a1685ce3f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DevicePropertyNotification.java @@ -0,0 +1,46 @@ +/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common; + +public class DevicePropertyNotification { + + /*** + * Serial number + */ + private String serial; + /*** + * IMEI number + */ + private String imei; + + public String getSerial() { + return serial; + } + + public void setSerial(String serial) { + this.serial = serial; + } + + public String getImei() { + return imei; + } + + public void setImei(String imei) { + this.imei = imei; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotificationConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotificationConfiguration.java new file mode 100644 index 0000000000..5937c92b99 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotificationConfiguration.java @@ -0,0 +1,89 @@ +/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.enrollment.notification; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * This class represents the information related to Enrollment Configuration configuration. + */ +@XmlRootElement(name = "EnrolmentNotificationConfiguration") +public class EnrollmentNotificationConfiguration { + + private boolean notifyThroughExtension; + private boolean enabled; + private String extensionClass; + private String notyfyingInternalHost; + + /** + * Enrollment Notification enabled + * + * @return If it is required to send notification for each enrollment, returns true otherwise returns false + */ + @XmlElement(name = "Enabled", required = true) + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setNotifyThroughExtension(boolean notifyThroughExtension) { + this.notifyThroughExtension = notifyThroughExtension; + } + + /** + * Enable notifying the enrollment through extension + * + * @return IF notifications are sending through the extension, returns true otherwise returns false + */ + @XmlElement(name = "NotifyThroughExtension", required = true) + public boolean getNotifyThroughExtension() { + return notifyThroughExtension; + } + + /** + * Extension Class + * + * @return extension full class path is returned + */ + @XmlElement(name = "ExtensionClass", required = true) + public String getExtensionClass() { + return extensionClass; + } + + public void setExtensionClass(String extensionClass) { + this.extensionClass = extensionClass; + } + + /** + * Extension Class + * + * @return extension full class path is returned + */ + @XmlElement(name = "NotifyingInternalHost", required = true) + public String getNotyfyingInternalHost() { + return notyfyingInternalHost; + } + + public void setNotyfyingInternalHost(String notyfyingInternalHost) { + this.notyfyingInternalHost = notyfyingInternalHost; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotifier.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotifier.java new file mode 100644 index 0000000000..4c94598c33 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotifier.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.enrollment.notification; + +import org.wso2.carbon.device.mgt.common.Device; + +/*** + * + */ +public interface EnrollmentNotifier { + + /*** + * notify method could be used to notify an enrollment of IoTS to a desired endpoint. This method could + * be invoked when a successful new enrollment completes. + * + * @throws EnrollmentNotifierException, if an error occurs while notify the enrollment to a defined end point + * + */ + void notify(Device device) throws EnrollmentNotifierException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotifierException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotifierException.java new file mode 100644 index 0000000000..1df3e80092 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/enrollment/notification/EnrollmentNotifierException.java @@ -0,0 +1,48 @@ +/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.enrollment.notification; + +/*** + * The EnrollmentNotifierException wraps all unchecked standard Java exception and this could be thrown if error occurs + * while notifying enrollment for defined endpoint and also if and only if enrollment notification is enabled. + * + */ +public class EnrollmentNotifierException extends Exception { + + private static final long serialVersionUID = -5980273112833902095L; + + public EnrollmentNotifierException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public EnrollmentNotifierException(String message, Throwable cause) { + super(message, cause); + } + + public EnrollmentNotifierException(String msg) { + super(msg); + } + + public EnrollmentNotifierException() { + super(); + } + + public EnrollmentNotifierException(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/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java index a7961c41fd..57b00cb5a8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java @@ -25,6 +25,7 @@ public final class DeviceManagementConstants { public static final String DM_CACHE_MANAGER = "DM_CACHE_MANAGER"; public static final String DEVICE_CACHE = "DEVICE_CACHE"; + public static final String ENROLLMENT_NOTIFICATION_API_ENDPOINT = "/api/device-mgt/enrollment-notification"; public static final class Common { private Common() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java index df57f65af4..456de2f2d4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java @@ -17,6 +17,7 @@ */ package org.wso2.carbon.device.mgt.core.config; +import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotificationConfiguration; import org.wso2.carbon.device.mgt.core.config.analytics.OperationAnalyticsConfiguration; import org.wso2.carbon.device.mgt.core.config.archival.ArchivalConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration; @@ -58,6 +59,7 @@ public final class DeviceManagementConfig { private String defaultGroupsConfiguration; private RemoteSessionConfiguration remoteSessionConfiguration; private ArchivalConfiguration archivalConfiguration; + private EnrollmentNotificationConfiguration enrollmentNotificationConfiguration; @XmlElement(name = "ManagementRepository", required = true) @@ -203,5 +205,15 @@ public final class DeviceManagementConfig { public void setRemoteSessionConfiguration(RemoteSessionConfiguration remoteSessionConfiguration) { this.remoteSessionConfiguration = remoteSessionConfiguration; } + + @XmlElement(name = "EnrolmentNotificationConfiguration", required = true) + public EnrollmentNotificationConfiguration getEnrollmentNotificationConfiguration() { + return enrollmentNotificationConfiguration; + } + + public void setEnrollmentNotificationConfiguration( + EnrollmentNotificationConfiguration enrollmentNotificationConfiguration) { + this.enrollmentNotificationConfiguration = enrollmentNotificationConfiguration; + } } 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 b1f2ffb043..e768749d7f 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 @@ -76,6 +76,17 @@ public interface DeviceDAO { */ int getDeviceCountByStatus(String status, int tenantId) throws DeviceManagementDAOException; + /** + * This method is used to get the device count by status and type. + * + * @param deviceType device type name. + * @param status enrollment status. + * @param tenantId tenant id. + * @return returns the device count of given status. + * @throws DeviceManagementDAOException + */ + int getDeviceCountByStatus(String deviceType, String status, int tenantId) throws DeviceManagementDAOException; + /** * This method is used to get the device count by ownership. * @@ -257,6 +268,11 @@ public interface DeviceDAO { */ int getDeviceCount(String username, int tenantId) throws DeviceManagementDAOException; + int getDeviceCount(String type, String status, int tenantId) throws DeviceManagementDAOException; + + List getDeviceIdentifiers(String type, String status, int tenantId) throws DeviceManagementDAOException; + + boolean setEnrolmentStatusInBulk(String deviceType, String status, int tenantId, List devices) throws DeviceManagementDAOException; /** * This method is used to retrieve the device count of a given tenant. * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java index 21cc243abe..843e8df646 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java @@ -25,7 +25,7 @@ import java.util.List; public interface EnrollmentDAO { - int addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException; + EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException; int updateEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, 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/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 2d0d877c03..66e15a47cf 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 @@ -39,7 +39,6 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; -import java.util.Iterator; import java.util.List; public abstract class AbstractDeviceDAOImpl implements DeviceDAO { @@ -515,6 +514,101 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { return deviceCount; } + /** + * Get device count of user. + * + * @return device count + * @throws DeviceManagementDAOException + */ + @Override + public int getDeviceCount(String type, String status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int deviceCount = 0; + try { + conn = this.getConnection(); + String sql = "SELECT COUNT(d.ID) AS DEVICE_COUNT FROM (SELECT e.DEVICE_ID FROM DM_ENROLMENT e WHERE " + + "TENANT_ID = ? AND STATUS = ?) e, DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.ID = e.DEVICE_ID AND " + + "d.DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ? AND t.NAME=?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, tenantId); + stmt.setString(2, status); + stmt.setInt(3, tenantId); + stmt.setString(4, type); + rs = stmt.executeQuery(); + if (rs.next()) { + deviceCount = rs.getInt("DEVICE_COUNT"); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while getting the device count", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return deviceCount; + } + + + public List getDeviceIdentifiers(String type, String status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + List deviceIDs = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT d.DEVICE_IDENTIFICATION AS DEVICE_IDS FROM (SELECT e.DEVICE_ID FROM DM_ENROLMENT e WHERE " + + "TENANT_ID = ? AND STATUS = ?) e, DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.ID = e.DEVICE_ID AND " + + "d.DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ? AND t.NAME=?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, tenantId); + stmt.setString(2, status); + stmt.setInt(3, tenantId); + stmt.setString(4, type); + rs = stmt.executeQuery(); + while (rs.next()) { + deviceIDs.add(rs.getString("DEVICE_IDS")); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving tenants which have " + + "device registered.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return deviceIDs; + } + + @Override + public boolean setEnrolmentStatusInBulk(String deviceType, String status, + int tenantId, List devices) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + StringBuilder sql = new StringBuilder("UPDATE DM_ENROLMENT SET STATUS = ? WHERE DEVICE_ID IN " + + "(SELECT d.ID FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.DEVICE_TYPE_ID = t.ID AND d.DEVICE_IDENTIFICATION IN ("); + for (int i = 0; i < devices.size(); i++) { + sql.append("?,"); + } + sql.deleteCharAt(sql.length() - 1); + sql.append(") AND t.NAME = ? AND d.TENANT_ID = ?) AND TENANT_ID = ?"); + stmt = conn.prepareStatement(sql.toString()); + stmt.setString(1, status); + int index = 1; + for (String device : devices) { + stmt.setString(++index, device); + } + stmt.setString(++index, deviceType); + stmt.setInt(++index, tenantId); + stmt.setInt(++index, tenantId); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrollment status in bulk", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + /** * Get device count of all devices. * @@ -769,8 +863,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { try { conn = this.getConnection(); String sql = "SELECT COUNT(d.ID) AS DEVICE_COUNT FROM (SELECT e.DEVICE_ID FROM DM_ENROLMENT e WHERE " + - "TENANT_ID = ? AND STATUS = ?) e, DM_DEVICE d, " + - "DM_DEVICE_TYPE t WHERE d.ID = e.DEVICE_ID AND d.DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ?"; + "TENANT_ID = ? AND STATUS = ?) e, DM_DEVICE d, " + + "DM_DEVICE_TYPE t WHERE d.ID = e.DEVICE_ID AND d.DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setInt(1, tenantId); stmt.setString(2, status); @@ -782,7 +876,36 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { } } catch (SQLException e) { throw new DeviceManagementDAOException("Error occurred while fetching the list of devices that matches to status " + - "'" + status + "'", e); + "'" + status + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return deviceCount; + } + + @Override + public int getDeviceCountByStatus(String deviceType, String status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + int deviceCount = 0; + try { + conn = this.getConnection(); + String sql = "SELECT COUNT(d.ID) AS DEVICE_COUNT FROM (SELECT e.DEVICE_ID FROM DM_ENROLMENT e WHERE " + + "TENANT_ID = ? AND STATUS = ?) e, DM_DEVICE d, " + + "DM_DEVICE_TYPE t WHERE t.NAME = ? AND d.ID = e.DEVICE_ID AND d.DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, tenantId); + stmt.setString(2, status); + stmt.setString(3, deviceType); + stmt.setInt(4, tenantId); + ResultSet rs = stmt.executeQuery(); + + if (rs.next()) { + deviceCount = rs.getInt("DEVICE_COUNT"); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while fetching the list of devices that matches to status " + + "'" + status + "'", e); } finally { DeviceManagementDAOUtil.cleanupResources(stmt, null); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java index b7a4086d0e..89e20dc242 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java @@ -36,31 +36,35 @@ import java.util.List; public class EnrollmentDAOImpl implements EnrollmentDAO { @Override - public int addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, + public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException { Connection conn; PreparedStatement stmt = null; ResultSet rs = null; - int enrolmentId = -1; try { conn = this.getConnection(); String sql = "INSERT INTO DM_ENROLMENT(DEVICE_ID, OWNER, OWNERSHIP, STATUS, " + "DATE_OF_ENROLMENT, DATE_OF_LAST_UPDATE, TENANT_ID) VALUES(?, ?, ?, ?, ?, ?, ?)"; stmt = conn.prepareStatement(sql, new String[] {"id"}); + Timestamp enrollmentTime = new Timestamp(new Date().getTime()); stmt.setInt(1, deviceId); stmt.setString(2, enrolmentInfo.getOwner()); stmt.setString(3, enrolmentInfo.getOwnership().toString()); stmt.setString(4, enrolmentInfo.getStatus().toString()); - stmt.setTimestamp(5, new Timestamp(new Date().getTime())); - stmt.setTimestamp(6, new Timestamp(new Date().getTime())); + stmt.setTimestamp(5, enrollmentTime); + stmt.setTimestamp(6, enrollmentTime); stmt.setInt(7, tenantId); stmt.execute(); rs = stmt.getGeneratedKeys(); if (rs.next()) { - enrolmentId = rs.getInt(1); + int enrolmentId = rs.getInt(1); + enrolmentInfo.setId(enrolmentId); + enrolmentInfo.setDateOfEnrolment(enrollmentTime.getTime()); + enrolmentInfo.setDateOfLastUpdate(enrollmentTime.getTime()); + return enrolmentInfo; } - return enrolmentId; + return null; } catch (SQLException e) { throw new DeviceManagementDAOException("Error occurred while adding enrolment configuration", e); } finally { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java index 89e541615c..d2fb72b90e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/operation/mgt/OperationManagerImpl.java @@ -147,8 +147,7 @@ public class OperationManagerImpl implements OperationManager { } @Override - public Activity addOperation(Operation operation, - List deviceIds) + public Activity addOperation(Operation operation, List deviceIds) throws OperationManagementException, InvalidDeviceException { if (log.isDebugEnabled()) { log.debug("operation:[" + operation.toString() + "]"); @@ -160,7 +159,13 @@ public class OperationManagerImpl implements OperationManager { try { DeviceIDHolder deviceValidationResult = DeviceManagerUtil.validateDeviceIdentifiers(deviceIds); List validDeviceIds = deviceValidationResult.getValidDeviceIDList(); - if (validDeviceIds.size() > 0) { + if (!validDeviceIds.isEmpty()) { + if (log.isDebugEnabled() && deviceIds.get(0).getType() != null) { + log.debug("Adding operation for Device type : " + deviceIds.get(0).getType() + ", tenant ID:" + + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId() + ", domain:" + + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain() + + ", device count:" + deviceIds.size() + " operation type:" + operation.getCode()); + } DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds); List authorizedDeviceIds = deviceAuthorizationResult.getValidDeviceIDList(); if (authorizedDeviceIds.size() <= 0) { @@ -285,6 +290,11 @@ public class OperationManagerImpl implements OperationManager { } private void sendNotification(Operation operation, Device device) { + if (log.isDebugEnabled()) { + log.debug("Sending notification for device id: " + device.getDeviceIdentifier() + ", type:" + device + .getType() + ", tenant:" + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId() + + ", domain:" + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()); + } NotificationStrategy notificationStrategy = getNotificationStrategy(); /* * If notification strategy has not enable to send push notification using scheduler task we will send @@ -315,6 +325,9 @@ public class OperationManagerImpl implements OperationManager { log.error("Error occurred while setting push notification status to SCHEDULED.", ex); OperationManagementDAOFactory.rollbackTransaction(); } + } catch (Exception e) { + log.error("Error occurred while sending notifications to " + device.getType() + " device carrying id '" + + device.getDeviceIdentifier() + "'", e); } } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/Constants.java index 0ba5bb7d10..a944aec330 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/Constants.java @@ -25,4 +25,7 @@ public class Constants { public static final String PROP_AND = "PROP_AND"; public static final String PROP_OR = "PROP_OR"; public static final String LOCATION = "LOCATION"; + + public static final String ANY_DEVICE_PERMISSION = "/device-mgt/devices/any-device"; + public static final String UI_EXECUTE = "ui.execute"; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ProcessorImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ProcessorImpl.java index e77f700fa8..5510247082 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ProcessorImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ProcessorImpl.java @@ -25,8 +25,6 @@ import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; -import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException; -import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.search.SearchContext; @@ -34,11 +32,21 @@ import org.wso2.carbon.device.mgt.core.dao.ApplicationDAO; 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.util.DeviceManagementDAOUtil; -import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; -import org.wso2.carbon.device.mgt.core.search.mgt.*; +import org.wso2.carbon.device.mgt.core.search.mgt.Constants; +import org.wso2.carbon.device.mgt.core.search.mgt.InvalidOperatorException; +import org.wso2.carbon.device.mgt.core.search.mgt.Processor; +import org.wso2.carbon.device.mgt.core.search.mgt.QueryBuilder; +import org.wso2.carbon.device.mgt.core.search.mgt.QueryHolder; +import org.wso2.carbon.device.mgt.core.search.mgt.ResultSetAggregator; +import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException; +import org.wso2.carbon.device.mgt.core.search.mgt.ValueType; import org.wso2.carbon.device.mgt.core.search.mgt.dao.SearchDAOException; -import java.sql.*; +import java.sql.Array; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -47,17 +55,9 @@ import java.util.Map; public class ProcessorImpl implements Processor { private ApplicationDAO applicationDAO; private static final Log log = LogFactory.getLog(ProcessorImpl.class); - private DeviceAccessAuthorizationService deviceAccessAuthorizationService; public ProcessorImpl() { applicationDAO = DeviceManagementDAOFactory.getApplicationDAO(); - deviceAccessAuthorizationService = DeviceManagementDataHolder.getInstance() - .getDeviceAccessAuthorizationService(); - if (deviceAccessAuthorizationService == null) { - String msg = "DeviceAccessAuthorization service has not initialized."; - log.error(msg); - throw new IllegalStateException(msg); - } } @Override @@ -115,35 +115,10 @@ public class ProcessorImpl implements Processor { devices.put(Constants.LOCATION, locationDevices); List finalDevices = aggregator.aggregate(devices); - finalDevices = authorizedDevices(finalDevices); this.setApplicationListOfDevices(finalDevices); return finalDevices; } - /** - * To get the authorized devices for a particular user - * - * @param devices Devices that satisfy search results - * @return Devices that satisfy search results and authorized to be viewed by particular user - */ - private List authorizedDevices(List devices) throws SearchMgtException { - List filteredList = new ArrayList<>(); - try { - for (Device device : devices) { - DeviceIdentifier deviceIdentifier = new DeviceIdentifier(device.getDeviceIdentifier(), - device.getType()); - if (deviceAccessAuthorizationService != null && deviceAccessAuthorizationService - .isUserAuthorized(deviceIdentifier)) { - filteredList.add(device); - } - } - return filteredList; - } catch (DeviceAccessAuthorizationException e) { - log.error("Error getting authorized search results for logged in user"); - throw new SearchMgtException(e); - } - } - @Override public List getUpdatedDevices(long epochTime) throws SearchMgtException { @@ -256,7 +231,6 @@ public class ProcessorImpl implements Processor { PreparedStatement stmt = null; ResultSet rs = null; List devices = new ArrayList<>(); - Map devs = new HashMap<>(); try { conn = this.getConnection(); stmt = conn.prepareStatement(queryHolder.getQuery()); @@ -281,59 +255,57 @@ public class ProcessorImpl implements Processor { rs = stmt.executeQuery(); while (rs.next()) { - if (!devs.containsKey(rs.getInt("ID"))) { - Device device = new Device(); - device.setId(rs.getInt("ID")); - device.setDescription(rs.getString("DESCRIPTION")); - device.setName(rs.getString("NAME")); - device.setType(rs.getString("DEVICE_TYPE_NAME")); - device.setDeviceIdentifier(rs.getString("DEVICE_IDENTIFICATION")); - - EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); - enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("DE_STATUS"))); - enrolmentInfo.setOwner(rs.getString("OWNER")); - enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); - device.setEnrolmentInfo(enrolmentInfo); - - DeviceIdentifier identifier = new DeviceIdentifier(); - identifier.setType(rs.getString("DEVICE_TYPE_NAME")); - identifier.setId(rs.getString("DEVICE_IDENTIFICATION")); - - DeviceInfo deviceInfo = new DeviceInfo(); - deviceInfo.setAvailableRAMMemory(rs.getDouble("AVAILABLE_RAM_MEMORY")); - deviceInfo.setBatteryLevel(rs.getDouble("BATTERY_LEVEL")); - deviceInfo.setConnectionType(rs.getString("CONNECTION_TYPE")); - deviceInfo.setCpuUsage(rs.getDouble("CPU_USAGE")); - deviceInfo.setDeviceModel(rs.getString("DEVICE_MODEL")); - deviceInfo.setExternalAvailableMemory(rs.getDouble("EXTERNAL_AVAILABLE_MEMORY")); - deviceInfo.setExternalTotalMemory(rs.getDouble("EXTERNAL_TOTAL_MEMORY")); - deviceInfo.setInternalAvailableMemory(rs.getDouble("INTERNAL_AVAILABLE_MEMORY")); - deviceInfo.setInternalTotalMemory(rs.getDouble("EXTERNAL_TOTAL_MEMORY")); - deviceInfo.setOsVersion(rs.getString("OS_VERSION")); - deviceInfo.setOsBuildDate(rs.getString("OS_BUILD_DATE")); - deviceInfo.setPluggedIn(rs.getBoolean("PLUGGED_IN")); - deviceInfo.setSsid(rs.getString("SSID")); - deviceInfo.setTotalRAMMemory(rs.getDouble("TOTAL_RAM_MEMORY")); - deviceInfo.setVendor(rs.getString("VENDOR")); - deviceInfo.setUpdatedTime(new java.util.Date(rs.getLong("UPDATE_TIMESTAMP"))); - - DeviceLocation deviceLocation = new DeviceLocation(); - deviceLocation.setLatitude(rs.getDouble("LATITUDE")); - deviceLocation.setLongitude(rs.getDouble("LONGITUDE")); - deviceLocation.setStreet1(rs.getString("STREET1")); - deviceLocation.setStreet2(rs.getString("STREET2")); - deviceLocation.setCity(rs.getString("CITY")); - deviceLocation.setState(rs.getString("STATE")); - deviceLocation.setZip(rs.getString("ZIP")); - deviceLocation.setCountry(rs.getString("COUNTRY")); - deviceLocation.setDeviceId(rs.getInt("ID")); - deviceLocation.setUpdatedTime(new java.util.Date(rs.getLong("DL_UPDATED_TIMESTAMP"))); - - deviceInfo.setLocation(deviceLocation); - device.setDeviceInfo(deviceInfo); - devices.add(device); - devs.put(device.getId(), device.getId()); - } + Device device = new Device(); + device.setId(rs.getInt("ID")); + device.setDescription(rs.getString("DESCRIPTION")); + device.setName(rs.getString("NAME")); + device.setType(rs.getString("DEVICE_TYPE_NAME")); + device.setDeviceIdentifier(rs.getString("DEVICE_IDENTIFICATION")); + + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setId(rs.getInt("ENROLLMENT_ID")); + enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("DE_STATUS"))); + enrolmentInfo.setOwner(rs.getString("OWNER")); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); + device.setEnrolmentInfo(enrolmentInfo); + + DeviceIdentifier identifier = new DeviceIdentifier(); + identifier.setType(rs.getString("DEVICE_TYPE_NAME")); + identifier.setId(rs.getString("DEVICE_IDENTIFICATION")); + + DeviceInfo deviceInfo = new DeviceInfo(); + deviceInfo.setAvailableRAMMemory(rs.getDouble("AVAILABLE_RAM_MEMORY")); + deviceInfo.setBatteryLevel(rs.getDouble("BATTERY_LEVEL")); + deviceInfo.setConnectionType(rs.getString("CONNECTION_TYPE")); + deviceInfo.setCpuUsage(rs.getDouble("CPU_USAGE")); + deviceInfo.setDeviceModel(rs.getString("DEVICE_MODEL")); + deviceInfo.setExternalAvailableMemory(rs.getDouble("EXTERNAL_AVAILABLE_MEMORY")); + deviceInfo.setExternalTotalMemory(rs.getDouble("EXTERNAL_TOTAL_MEMORY")); + deviceInfo.setInternalAvailableMemory(rs.getDouble("INTERNAL_AVAILABLE_MEMORY")); + deviceInfo.setInternalTotalMemory(rs.getDouble("EXTERNAL_TOTAL_MEMORY")); + deviceInfo.setOsVersion(rs.getString("OS_VERSION")); + deviceInfo.setOsBuildDate(rs.getString("OS_BUILD_DATE")); + deviceInfo.setPluggedIn(rs.getBoolean("PLUGGED_IN")); + deviceInfo.setSsid(rs.getString("SSID")); + deviceInfo.setTotalRAMMemory(rs.getDouble("TOTAL_RAM_MEMORY")); + deviceInfo.setVendor(rs.getString("VENDOR")); + deviceInfo.setUpdatedTime(new java.util.Date(rs.getLong("UPDATE_TIMESTAMP"))); + + DeviceLocation deviceLocation = new DeviceLocation(); + deviceLocation.setLatitude(rs.getDouble("LATITUDE")); + deviceLocation.setLongitude(rs.getDouble("LONGITUDE")); + deviceLocation.setStreet1(rs.getString("STREET1")); + deviceLocation.setStreet2(rs.getString("STREET2")); + deviceLocation.setCity(rs.getString("CITY")); + deviceLocation.setState(rs.getString("STATE")); + deviceLocation.setZip(rs.getString("ZIP")); + deviceLocation.setCountry(rs.getString("COUNTRY")); + deviceLocation.setDeviceId(rs.getInt("ID")); + deviceLocation.setUpdatedTime(new java.util.Date(rs.getLong("DL_UPDATED_TIMESTAMP"))); + + deviceInfo.setLocation(deviceLocation); + device.setDeviceInfo(deviceInfo); + devices.add(device); } } catch (SQLException e) { throw new SearchDAOException("Error occurred while aquiring the device details.", e); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/QueryBuilderImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/QueryBuilderImpl.java index 65b6af46fa..27e6457a2f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/QueryBuilderImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/QueryBuilderImpl.java @@ -331,7 +331,7 @@ public class QueryBuilderImpl implements QueryBuilder { "DD.EXTERNAL_TOTAL_MEMORY, DD.EXTERNAL_AVAILABLE_MEMORY, DD.CONNECTION_TYPE, \n" + "DD.SSID, DD.CPU_USAGE, DD.TOTAL_RAM_MEMORY, DD.AVAILABLE_RAM_MEMORY, \n" + "DD.PLUGGED_IN, DD.UPDATE_TIMESTAMP, DL.LATITUDE, DL.LONGITUDE, DL.STREET1, DL.STREET2, DL.CITY, DL.ZIP, \n" + - "DL.STATE, DL.COUNTRY, DL.UPDATE_TIMESTAMP AS DL_UPDATED_TIMESTAMP, DE.OWNER, DE.OWNERSHIP, DE.STATUS " + + "DL.STATE, DL.COUNTRY, DL.UPDATE_TIMESTAMP AS DL_UPDATED_TIMESTAMP, DE.ID AS ENROLLMENT_ID, DE.OWNER, DE.OWNERSHIP, DE.STATUS " + "AS DE_STATUS FROM DM_DEVICE_DETAIL DD INNER JOIN DM_DEVICE D ON D.ID=DD.DEVICE_ID\n" + "LEFT JOIN DM_DEVICE_LOCATION DL ON DL.DEVICE_ID=D.ID \n" + "INNER JOIN DM_DEVICE_TYPE DT ON DT.ID=D.DEVICE_TYPE_ID\n" + @@ -359,7 +359,7 @@ public class QueryBuilderImpl implements QueryBuilder { "DD.SSID, DD.CPU_USAGE, DD.TOTAL_RAM_MEMORY, DD.AVAILABLE_RAM_MEMORY, \n" + "DD.PLUGGED_IN, DD.UPDATE_TIMESTAMP, DL.LATITUDE, DL.LONGITUDE, DL.STREET1, DL.STREET2, DL.CITY, DL.ZIP, \n" + "DL.STATE, DL.COUNTRY, DL.UPDATE_TIMESTAMP AS DL_UPDATED_TIMESTAMP, DI.KEY_FIELD, DI.VALUE_FIELD, \n" + - "DE.OWNER, DE.OWNERSHIP, DE.STATUS AS DE_STATUS " + + "DE.ID ENROLLMENT_ID, DE.OWNER, DE.OWNERSHIP, DE.STATUS AS DE_STATUS " + "FROM DM_DEVICE_DETAIL DD INNER JOIN DM_DEVICE D ON D.ID=DD.DEVICE_ID\n" + "LEFT JOIN DM_DEVICE_LOCATION DL ON DL.DEVICE_ID=D.ID \n" + "INNER JOIN DM_DEVICE_TYPE DT ON DT.ID=D.DEVICE_TYPE_ID\n" + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ResultSetAggregatorImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ResultSetAggregatorImpl.java index acc565a9af..cdb6322ca6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ResultSetAggregatorImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/search/mgt/impl/ResultSetAggregatorImpl.java @@ -19,9 +19,16 @@ package org.wso2.carbon.device.mgt.core.search.mgt.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.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionUtils; import org.wso2.carbon.device.mgt.core.search.mgt.Constants; import org.wso2.carbon.device.mgt.core.search.mgt.ResultSetAggregator; +import org.wso2.carbon.user.api.UserRealm; +import org.wso2.carbon.user.api.UserStoreException; import java.util.ArrayList; import java.util.HashMap; @@ -29,16 +36,17 @@ import java.util.List; import java.util.Map; public class ResultSetAggregatorImpl implements ResultSetAggregator { + private static Log log = LogFactory.getLog(ResultSetAggregatorImpl.class); @Override public List aggregate(Map> devices) { - Map generalQueryMap = this.convertToMap(devices.get(Constants.GENERAL)); Map andMap = this.convertToMap(devices.get(Constants.PROP_AND)); Map orMap = this.convertToMap(devices.get(Constants.PROP_OR)); Map locationMap = this.convertToMap(devices.get(Constants.LOCATION)); Map finalMap = new HashMap<>(); List finalResult = new ArrayList<>(); + List ownDevices = new ArrayList<>(); if (andMap.isEmpty()) { finalMap = generalQueryMap; @@ -70,7 +78,23 @@ public class ResultSetAggregatorImpl implements ResultSetAggregator { } } - return finalResult; + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + + try { + if (isPermittedToViewAnyDevice(username)) { + return finalResult; + } + } catch (UserStoreException e) { + log.error("Unable to check permissions of the user: " + username, e); + } + + for (Device device: finalResult) { + if (username.equals(device.getEnrolmentInfo().getOwner())) { + ownDevices.add(device); + } + } + + return ownDevices; } private Map convertToMap(List devices) { @@ -79,7 +103,7 @@ public class ResultSetAggregatorImpl implements ResultSetAggregator { } Map deviceWrapperMap = new HashMap<>(); for (Device device : devices) { - deviceWrapperMap.put(device.getId(), device); + deviceWrapperMap.put(device.getEnrolmentInfo().getId(), device); } return deviceWrapperMap; } @@ -92,4 +116,20 @@ public class ResultSetAggregatorImpl implements ResultSetAggregator { return list; } + /** + * Checks if the user has permissions to view all devices. + * + * @param username username + * @return {@code true} if user is permitted + * @throws UserStoreException If unable to check user permissions + */ + private boolean isPermittedToViewAnyDevice(String username) throws UserStoreException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + UserRealm userRealm = DeviceManagementDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId); + return userRealm != null && userRealm.getAuthorizationManager() != null && + userRealm.getAuthorizationManager().isUserAuthorized(username, + PermissionUtils.getAbsolutePermissionPath(Constants.ANY_DEVICE_PERMISSION), + Constants.UI_EXECUTE); + } + } 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 504ee52dbe..c970b593cb 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 @@ -27,7 +27,6 @@ import org.wso2.carbon.device.mgt.common.MonitoringOperation; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; 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.DeviceApplicationMapping; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.license.mgt.License; @@ -466,6 +465,29 @@ public interface DeviceManagementProviderService { */ int getDeviceCount() throws DeviceManagementException; + /** + * Method to get the count of devices with given status and type. + * + * @param deviceType Device type name + * @param status Device status + * + * @return device count + * @throws DeviceManagementException If some unusual behaviour is observed while counting + * the devices + */ + int getDeviceCount(String deviceType, EnrolmentInfo.Status status) throws DeviceManagementException; + + /** + * Method to get the count of all types of devices with given status. + * + * @param status Device status + * + * @return device count + * @throws DeviceManagementException If some unusual behaviour is observed while counting + * the devices + */ + int getDeviceCount(EnrolmentInfo.Status status) throws DeviceManagementException; + HashMap getTenantedDevice(DeviceIdentifier deviceIdentifier) throws DeviceManagementException; void sendEnrolmentInvitation(String templateName, EmailMetaInfo metaInfo) throws DeviceManagementException, @@ -638,4 +660,10 @@ public interface DeviceManagementProviderService { List findGeoClusters(String deviceType, GeoCoordinate southWest, GeoCoordinate northEast, int geohashLength) throws DeviceManagementException; + + int getDeviceCountOfTypeByStatus(String deviceType, String deviceStatus) throws DeviceManagementException; + + List getDeviceIdentifiersByStatus(String deviceType, String deviceStatus) throws DeviceManagementException; + + boolean bulkUpdateDeviceStatus(String deviceType, List deviceList, String status) 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 278d2d0d47..c7a3a5aabc 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 @@ -20,11 +20,19 @@ 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.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.protocol.HTTP; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceEnrollmentInfoNotification; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManager; @@ -34,6 +42,8 @@ import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecu import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; import org.wso2.carbon.device.mgt.core.dao.ApplicationMappingDAO; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeServiceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceNotification; +import org.wso2.carbon.device.mgt.common.DevicePropertyNotification; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.FeatureManager; import org.wso2.carbon.device.mgt.common.InitialOperationConfig; @@ -48,6 +58,9 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManageme import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; +import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotificationConfiguration; +import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifier; +import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifierException; 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.GroupAlreadyExistException; @@ -59,13 +72,13 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; -import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException; -import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.DeviceManagementPluginRepository; import org.wso2.carbon.device.mgt.core.cache.impl.DeviceCacheManagerImpl; +import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; +import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig; import org.wso2.carbon.device.mgt.core.dao.ApplicationDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; @@ -77,7 +90,6 @@ import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsDAO; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsMgtDAOException; import org.wso2.carbon.device.mgt.core.device.details.mgt.impl.DeviceInformationManagerImpl; 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.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; @@ -93,6 +105,11 @@ import org.wso2.carbon.email.sender.core.TypedValue; import org.wso2.carbon.email.sender.core.service.EmailSenderService; import org.wso2.carbon.user.api.UserStoreException; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import java.io.IOException; +import java.io.StringWriter; import java.sql.SQLException; import java.util.ArrayList; import java.util.Calendar; @@ -213,6 +230,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv if (enrolmentInfo.equals(newEnrolmentInfo)) { device.setId(existingDevice.getId()); device.getEnrolmentInfo().setDateOfEnrolment(enrolmentInfo.getDateOfEnrolment()); + device.getEnrolmentInfo().setDateOfLastUpdate(enrolmentInfo.getDateOfLastUpdate()); device.getEnrolmentInfo().setId(enrolmentInfo.getId()); this.modifyEnrollment(device); status = true; @@ -220,7 +238,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } if (!status) { - int enrolmentId, updateStatus = 0; + int updateStatus = 0; + EnrolmentInfo enrollment; try { //Remove the existing enrollment DeviceManagementDAOFactory.beginTransaction(); @@ -230,12 +249,20 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } if ((updateStatus > 0) || EnrolmentInfo.Status.REMOVED. equals(existingEnrolmentInfo.getStatus())) { - enrolmentId = enrollmentDAO. + enrollment = enrollmentDAO. addEnrollment(existingDevice.getId(), newEnrolmentInfo, tenantId); + if (enrollment == null ){ + DeviceManagementDAOFactory.rollbackTransaction(); + throw new DeviceManagementException( + "Enrollment data persistence is failed in a re-enrollment. Device id : " + + existingDevice.getId() + " Device Identifier: " + device + .getDeviceIdentifier()); + } + device.setEnrolmentInfo(enrollment); DeviceManagementDAOFactory.commitTransaction(); this.removeDeviceFromCache(deviceIdentifier); if (log.isDebugEnabled()) { - log.debug("An enrolment is successfully added with the id '" + enrolmentId + + log.debug("An enrolment is successfully added with the id '" + enrollment.getId() + "' associated with " + "the device identified by key '" + device.getDeviceIdentifier() + "', which belongs to " + "platform '" + device.getType() + " upon the user '" + device.getEnrolmentInfo().getOwner() + @@ -261,13 +288,20 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } } else { - int enrolmentId; + EnrolmentInfo enrollment; try { DeviceManagementDAOFactory.beginTransaction(); DeviceType type = deviceTypeDAO.getDeviceType(device.getType(), tenantId); if (type != null) { int deviceId = deviceDAO.addDevice(type.getId(), device, tenantId); - enrolmentId = enrollmentDAO.addEnrollment(deviceId, device.getEnrolmentInfo(), tenantId); + enrollment = enrollmentDAO.addEnrollment(deviceId, device.getEnrolmentInfo(), tenantId); + if (enrollment == null ){ + DeviceManagementDAOFactory.rollbackTransaction(); + throw new DeviceManagementException( + "Enrollment data persistence is failed in a new enrollment. Device id: " + deviceId + + " Device Identifier: " + device.getDeviceIdentifier()); + } + device.setEnrolmentInfo(enrollment); DeviceManagementDAOFactory.commitTransaction(); } else { DeviceManagementDAOFactory.rollbackTransaction(); @@ -294,17 +328,17 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } if (log.isDebugEnabled()) { - log.debug("An enrolment is successfully created with the id '" + enrolmentId + "' associated with " + + log.debug("An enrolment is successfully created with the id '" + enrollment.getId() + "' associated with " + "the device identified by key '" + device.getDeviceIdentifier() + "', which belongs to " + "platform '" + device.getType() + " upon the user '" + device.getEnrolmentInfo().getOwner() + "'"); } status = true; } - if (status) { addDeviceToGroups(deviceIdentifier, device.getEnrolmentInfo().getOwnership()); addInitialOperations(deviceIdentifier, device.getType()); + sendNotification(device); } extractDeviceLocationToUpdate(device); return status; @@ -1929,6 +1963,57 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } + @Override + public int getDeviceCount(String deviceType, EnrolmentInfo.Status status) throws DeviceManagementException { + if (log.isDebugEnabled()) { + log.debug("Get devices count for type '" + deviceType + "' and status: " + status.toString()); + } + try { + DeviceManagementDAOFactory.openConnection(); + return deviceDAO.getDeviceCountByStatus(deviceType, status.toString(), this.getTenantId()); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving the device count for type '" + deviceType + + "' and status: " + status.toString(); + 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); + } catch (Exception e) { + String msg = "Error occurred in getDeviceCount for type '" + deviceType + "' and status: " + status.toString(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public int getDeviceCount(EnrolmentInfo.Status status) throws DeviceManagementException { + if (log.isDebugEnabled()) { + log.debug("Get devices count status: " + status.toString()); + } + try { + DeviceManagementDAOFactory.openConnection(); + return deviceDAO.getDeviceCountByStatus(status.toString(), this.getTenantId()); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving the device count"; + 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); + } catch (Exception e) { + String msg = "Error occurred in getDeviceCount status: " + status.toString(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + @Override public List getDevicesByNameAndType(PaginationRequest request, boolean requireDeviceInfo) throws DeviceManagementException { @@ -2692,6 +2777,68 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } + @Override + public int getDeviceCountOfTypeByStatus(String deviceType, String deviceStatus) throws DeviceManagementException { + int tenantId = this.getTenantId(); + try { + DeviceManagementDAOFactory.openConnection(); + return deviceDAO.getDeviceCount(deviceType, deviceStatus, tenantId); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred in while retrieving device count by status for deviceType :" +deviceType + " status : " + deviceStatus; + 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(); + } + } + + @Override + public List getDeviceIdentifiersByStatus(String deviceType, String deviceStatus) throws DeviceManagementException { + int tenantId = this.getTenantId(); + List deviceIds; + try { + DeviceManagementDAOFactory.openConnection(); + deviceIds = deviceDAO.getDeviceIdentifiers(deviceType, deviceStatus, tenantId); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred in while retrieving devices by status for deviceType :" +deviceType + " status : " + deviceStatus; + 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(); + } + return deviceIds; + } + + @Override + public boolean bulkUpdateDeviceStatus(String deviceType, List deviceList, String status) throws DeviceManagementException { + int tenantId = this.getTenantId(); + boolean success; + try { + DeviceManagementDAOFactory.openConnection(); + success = deviceDAO.setEnrolmentStatusInBulk(deviceType, status, tenantId, deviceList); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred in while updating status of devices :" +deviceType + " status : " + deviceList.toString(); + 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(); + } + return success; + } + private void extractDeviceLocationToUpdate(Device device) { List properties = device.getProperties(); if (properties != null) { @@ -2726,4 +2873,120 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } + /*** + * + *

+ * If the device enrollment is succeeded and the enrollment notification sending is enabled, this method executes. + * If it is configured to send enrollment notification by using the extension, initiate the instance from + * configured instance class and execute the notify method to send enrollment notification. + *

+ * + *

+ * In default, if it is enabled the enrollment notification sending and disabled the notifying through extension, + * it uses pre-defined API to send enrollment notification. In that case, invoke the + * /api/device-mgt/enrollment-notification API with the constructed payload. + *

+ * @param device {@link Device} object + */ + private void sendNotification(Device device) { + DeviceManagementConfig config = DeviceConfigurationManager.getInstance().getDeviceManagementConfig(); + EnrollmentNotificationConfiguration enrollmentNotificationConfiguration = config + .getEnrollmentNotificationConfiguration(); + try { + if (enrollmentNotificationConfiguration != null && enrollmentNotificationConfiguration.isEnabled()) { + if (enrollmentNotificationConfiguration.getNotifyThroughExtension()) { + Class clz = Class.forName(enrollmentNotificationConfiguration.getExtensionClass()); + EnrollmentNotifier enrollmentNotifier = (EnrollmentNotifier) clz.newInstance(); + enrollmentNotifier.notify(device); + } else { + String internalServerAddr = enrollmentNotificationConfiguration.getNotyfyingInternalHost(); + if (internalServerAddr == null) { + internalServerAddr = "https://localhost:8243"; + } + invokeApi(device, internalServerAddr); + } + } else { + if (log.isDebugEnabled()) { + log.debug( + "Either Enrollment Notification Configuration is disabled or not defined in the cdm-config.xml"); + } + } + } catch (ClassNotFoundException e) { + log.error("Extension class cannot be located", e); + } catch (IllegalAccessException e) { + log.error("Can't access the class or its nullary constructor is not accessible.", e); + } catch (InstantiationException e) { + log.error("Extension class instantiation is failed", e); + } catch (EnrollmentNotifierException e) { + log.error("Error occured while sending enrollment notification." + e); + } + } + + private void invokeApi(Device device, String internalServerAddr) throws EnrollmentNotifierException { + try (CloseableHttpClient client = HttpClients.createDefault()) { + HttpPost apiEndpoint = new HttpPost( + internalServerAddr + DeviceManagementConstants.ENROLLMENT_NOTIFICATION_API_ENDPOINT); + apiEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_XML.toString()); + apiEndpoint.setEntity(constructEnrollmentNotificationPayload(device)); + HttpResponse response = client.execute(apiEndpoint); + if (response != null) { + log.info("Enrollment Notification is sent through a configured API. Response code: " + response + .getStatusLine().getStatusCode()); + } else { + log.error("Response is 'NUll' for the Enrollment notification sending API call."); + } + } catch (IOException e) { + throw new EnrollmentNotifierException("Error occured when invoking API. API endpoint: " + internalServerAddr + + DeviceManagementConstants.ENROLLMENT_NOTIFICATION_API_ENDPOINT, e); + } + } + + /*** + * + * Convert device object into XML string and construct {@link StringEntity} object and returns. + *

+ * First create {@link JAXBContext} and thereafter create {@link Marshaller} by usig created {@link JAXBContext}. + * Then enable formatting and get the converted xml string output of {@link Device}. + *

+ * + * @param device {@link Device} object + * @return {@link StringEntity} + * @throws EnrollmentNotifierException, if error occured while converting {@link Device} object into XML sting + */ + private static StringEntity constructEnrollmentNotificationPayload(Device device) + throws EnrollmentNotifierException { + try { + DevicePropertyNotification devicePropertyNotification = new DevicePropertyNotification(); + for (Device.Property property : device.getProperties()) { + if ("SERIAL".equals(property.getName())) { + devicePropertyNotification.setSerial(property.getValue()); + } + if ("IMEI".equals((property.getName()))) { + devicePropertyNotification.setImei(property.getValue()); + } + } + DeviceEnrollmentInfoNotification deviceEnrollmentInfoNotification = new DeviceEnrollmentInfoNotification(); + deviceEnrollmentInfoNotification.setOwner(device.getEnrolmentInfo().getOwner()); + deviceEnrollmentInfoNotification.setDateOfEnrolment(device.getEnrolmentInfo().getDateOfEnrolment()); + deviceEnrollmentInfoNotification.setDateOfLastUpdate(device.getEnrolmentInfo().getDateOfLastUpdate()); + deviceEnrollmentInfoNotification.setOwnership(device.getEnrolmentInfo().getOwnership().toString()); + deviceEnrollmentInfoNotification.setStatus(device.getEnrolmentInfo().getStatus().toString()); + + DeviceNotification deviceNotification = new DeviceNotification(device.getDeviceIdentifier(), device.getName(), + device.getType(), device.getDescription(), devicePropertyNotification, + deviceEnrollmentInfoNotification); + + JAXBContext jaxbContext = JAXBContext.newInstance(DeviceNotification.class); + Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); + jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + StringWriter sw = new StringWriter(); + jaxbMarshaller.marshal(deviceNotification, sw); + String payload = sw.toString(); + return new StringEntity(payload, ContentType.APPLICATION_XML); + } catch (JAXBException e) { + throw new EnrollmentNotifierException( + "Error occured when converting Device object into xml string. Hence enrollment notification payload " + + "constructing is failed", e); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java index 567964d808..f411c3d9f8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java @@ -86,6 +86,10 @@ public class DeviceDetailsRetrieverTask implements Task { try { List tenants = DeviceManagementDataHolder.getInstance(). getDeviceManagementProvider().getDeviceEnrolledTenants(); + if (log.isDebugEnabled()) { + log.debug("Task is running for " + tenants.size() + " tenants and the device type is " + deviceType); + } + for (Integer tenant : tenants) { String tenantDomain = DeviceManagementDataHolder.getInstance(). getRealmService().getTenantManager().getDomain(tenant); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceTaskManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceTaskManagerImpl.java index 2132889189..602e656f90 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceTaskManagerImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceTaskManagerImpl.java @@ -22,6 +22,7 @@ package org.wso2.carbon.device.mgt.core.task.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.MonitoringOperation; @@ -84,18 +85,26 @@ public class DeviceTaskManagerImpl implements DeviceTaskManager { try { List devices; List operations; - + List validDeviceIdentifiers; operations = this.getValidOperationNames(); //list operations for each device type devices = deviceManagementProviderService.getAllDevices(deviceType, false);//list devices for each type + if (!devices.isEmpty()) { - if (operations != null && DeviceManagerUtil.getValidDeviceIdentifiers(devices).size() != 0) { + if (log.isDebugEnabled() && deviceType != null) { + log.info("Devices exist to add operations and the total number of devices are " + devices.size()); + } + validDeviceIdentifiers = DeviceManagerUtil.getValidDeviceIdentifiers(devices); + if (!validDeviceIdentifiers.isEmpty()) { + if (log.isDebugEnabled() && deviceType != null) { + log.debug("Number of valid device identifier size to add operations: " + validDeviceIdentifiers + .size()); + } for (String str : operations) { CommandOperation operation = new CommandOperation(); operation.setEnabled(true); operation.setType(Operation.Type.COMMAND); operation.setCode(str); - deviceManagementProviderService.addOperation(deviceType, operation, - DeviceManagerUtil.getValidDeviceIdentifiers(devices)); + deviceManagementProviderService.addOperation(deviceType, operation, validDeviceIdentifiers); } } else { if (log.isDebugEnabled()) { @@ -174,4 +183,3 @@ public class DeviceTaskManagerImpl implements DeviceTaskManager { } } - diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/search/ProcessorImplTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/search/ProcessorImplTest.java index 92f3eac37d..221ed02461 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/search/ProcessorImplTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/search/ProcessorImplTest.java @@ -17,14 +17,11 @@ */ package org.wso2.carbon.device.mgt.core.search; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; import org.wso2.carbon.device.mgt.common.search.Condition; import org.wso2.carbon.device.mgt.common.search.SearchContext; import org.wso2.carbon.device.mgt.core.TestDeviceManagementService; @@ -41,7 +38,6 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; @@ -50,16 +46,12 @@ import java.util.List; */ public class ProcessorImplTest extends BaseDeviceManagementTest { - private DeviceAccessAuthorizationService deviceAccessAuthorizationService; - private static final Log log = LogFactory.getLog(SearchManagementServiceTest.class); private static List deviceIdentifiers = new ArrayList<>(); private static final String DEVICE_ID_PREFIX = "SEARCH-DEVICE-ID-"; private static final String DEVICE_TYPE = "SEARCH_TYPE"; @BeforeClass public void init() throws Exception { - deviceAccessAuthorizationService = DeviceManagementDataHolder.getInstance() - .getDeviceAccessAuthorizationService(); for (int i = 0; i < 5; i++) { deviceIdentifiers.add(new DeviceIdentifier(DEVICE_ID_PREFIX + i, DEVICE_TYPE)); } @@ -81,27 +73,59 @@ public class ProcessorImplTest extends BaseDeviceManagementTest { } } - @Test(description = "Test the Search Processor") - public void testWithNoDeviceAccessAuthorization() throws NoSuchFieldException, IllegalAccessException, - SearchMgtException { + @Test (description = "Search for device with and condition") + public void testSearchDevicesWIthAndCondition() throws SearchMgtException { SearchContext context = new SearchContext(); List conditions = new ArrayList<>(); - Condition cond = new Condition(); - cond.setKey("batteryLevel"); - cond.setOperator("="); - cond.setValue("40"); - cond.setState(Condition.State.AND); - conditions.add(cond); + + Condition condition = new Condition(); + condition.setKey("IMEI"); + condition.setOperator("="); + condition.setValue("e6f236ac82537a8e"); + condition.setState(Condition.State.AND); + conditions.add(condition); + + context.setConditions(conditions); + ProcessorImpl processor = new ProcessorImpl(); + List devices = processor.execute(context); + Assert.assertEquals(5, devices.size(), "There should be exactly 5 devices with matching search criteria"); + } + + @Test (description = "Search for device with or condition") + public void testSearchDevicesWIthORCondition() throws SearchMgtException { + SearchContext context = new SearchContext(); + List conditions = new ArrayList<>(); + + Condition condition = new Condition(); + condition.setKey("IMSI"); + condition.setOperator("="); + condition.setValue("432659632123654845"); + condition.setState(Condition.State.OR); + conditions.add(condition); + context.setConditions(conditions); ProcessorImpl processor = new ProcessorImpl(); - Field deviceAccessAuthorizationServiceField = ProcessorImpl.class.getDeclaredField - ("deviceAccessAuthorizationService"); - deviceAccessAuthorizationServiceField.setAccessible(true); - deviceAccessAuthorizationServiceField.set(processor, null); - List searchedDevices = processor.execute(context); - Assert.assertEquals(0, searchedDevices.size()); + List devices = processor.execute(context); + Assert.assertEquals(5, devices.size(), "There should be exactly 5 devices with matching search criteria"); } + @Test (description = "Search for device with wrong condition") + public void testSearchDevicesWIthWrongCondition() throws SearchMgtException { + SearchContext context = new SearchContext(); + List conditions = new ArrayList<>(); + + Condition condition = new Condition(); + condition.setKey("IMSI"); + condition.setOperator("="); + condition.setValue("43265963212378466"); + condition.setState(Condition.State.OR); + conditions.add(condition); + + context.setConditions(conditions); + ProcessorImpl processor = new ProcessorImpl(); + List devices = processor.execute(context); + Assert.assertEquals(0, devices.size(), "There should be no devices with matching search criteria"); + } @Test(description = "Test for invalid state") public void testInvalidState() throws SearchMgtException { @@ -141,16 +165,4 @@ public class ProcessorImplTest extends BaseDeviceManagementTest { } } } - - @Test(description = "Test when Device Access Authorization is null", expectedExceptions = {IllegalStateException - .class}, dependsOnMethods = {"testWithNoDeviceAccessAuthorization", "testInvalidState"}) - public void testProcessorInitializationError() throws ClassNotFoundException, NoSuchMethodException, - NoSuchFieldException, IllegalAccessException, SearchMgtException { - DeviceManagementDataHolder deviceManagementDataHolder = DeviceManagementDataHolder.getInstance(); - Field field = DeviceManagementDataHolder.class.getDeclaredField("deviceAccessAuthorizationService"); - field.setAccessible(true); - field.set(deviceManagementDataHolder, null); - ProcessorImpl processor = new ProcessorImpl(); - processor.execute(null); - } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceTest.java index 22d7098c74..ffff69c6a5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceTest.java @@ -301,7 +301,7 @@ public class DeviceManagementProviderServiceTest extends BaseDeviceManagementTes @Test(expectedExceptions = DeviceManagementException.class) public void testGetDeviceCountForNullUser() throws DeviceManagementException { - deviceMgtService.getDeviceCount(null); + deviceMgtService.getDeviceCount((String) null); } @Test(dependsOnMethods = {"testSuccessfulDeviceEnrollment"}) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mssql-testng.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mssql-testng.xml index 5c1f4cbe4e..8f0a9de713 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mssql-testng.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mssql-testng.xml @@ -40,7 +40,7 @@ - + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mysql-testng.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mysql-testng.xml index 7b02276ea6..4240faeb80 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mysql-testng.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/mysql-testng.xml @@ -40,7 +40,7 @@ - + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/oracle-testng.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/oracle-testng.xml index cb41dfc620..9ec34795d4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/oracle-testng.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/oracle-testng.xml @@ -40,7 +40,7 @@ - + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/postgre-testng.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/postgre-testng.xml index 6c516bc74d..fbaf2fd8a7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/postgre-testng.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/postgre-testng.xml @@ -40,7 +40,7 @@ - + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/license/mgt/registry/RegistryBasedLicenseManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/license/mgt/registry/RegistryBasedLicenseManager.java index 0c5b6707ac..0d62134675 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/license/mgt/registry/RegistryBasedLicenseManager.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/license/mgt/registry/RegistryBasedLicenseManager.java @@ -44,17 +44,18 @@ import java.util.Locale; @SuppressWarnings("unused") public class RegistryBasedLicenseManager implements LicenseManager { - private GenericArtifactManager artifactManager; private static final Log log = LogFactory.getLog(RegistryBasedLicenseManager.class); - public RegistryBasedLicenseManager() { + public RegistryBasedLicenseManager() {} + + private GenericArtifactManager getArtifactManager() { Registry registry = CarbonContext.getThreadLocalCarbonContext().getRegistry(RegistryType.SYSTEM_GOVERNANCE); if (registry == null) { throw new IllegalArgumentException("Registry instance retrieved is null. Hence, " + "'Registry based license manager cannot be initialized'"); } try { - this.artifactManager = GenericArtifactManagerFactory.getTenantAwareGovernanceArtifactManager(registry); + return GenericArtifactManagerFactory.getTenantAwareGovernanceArtifactManager(registry); } catch (LicenseManagementException e) { throw new IllegalStateException("Failed to initialize generic artifact manager bound to " + "Registry based license manager", e); @@ -63,14 +64,17 @@ public class RegistryBasedLicenseManager implements LicenseManager { @Override public License getLicense(final String deviceType, final String languageCode) throws LicenseManagementException { + GenericArtifactManager artifactManager = getArtifactManager(); try { - GenericArtifact artifact = this.getGenericArtifact(deviceType, languageCode); - if (artifact == null) { - if (log.isDebugEnabled()) { - log.debug("Generic artifact is null for '" + deviceType + "' device type. Hence license does not " + - "have content"); - } - return null; + GenericArtifact artifact = this.getGenericArtifact(artifactManager, deviceType, languageCode); + if (artifact == null) { //Adding a default license + License license = new License(); + license.setName(deviceType); + license.setVersion("1.0.0"); + license.setLanguage("en_US"); + license.setText("This is license text"); + addLicense(deviceType, license); + return license; } return this.populateLicense(artifact); } catch (GovernanceException e) { @@ -104,8 +108,9 @@ public class RegistryBasedLicenseManager implements LicenseManager { @Override public void addLicense(final String deviceType, final License license) throws LicenseManagementException { + GenericArtifactManager artifactManager = getArtifactManager(); try { - GenericArtifact artifact = this.getGenericArtifact(deviceType, license.getLanguage()); + GenericArtifact artifact = this.getGenericArtifact(artifactManager, deviceType, license.getLanguage()); if(artifact != null) { artifact.setAttribute(DeviceManagementConstants.LicenseProperties.NAME, license.getName()); artifact.setAttribute(DeviceManagementConstants.LicenseProperties.VERSION, license.getVersion()); @@ -147,8 +152,8 @@ public class RegistryBasedLicenseManager implements LicenseManager { } } - private GenericArtifact getGenericArtifact(final String deviceType, final String languageCode) - throws GovernanceException { + private GenericArtifact getGenericArtifact(GenericArtifactManager artifactManager, final String deviceType, final + String languageCode) throws GovernanceException { GenericArtifact[] artifacts = artifactManager.findGenericArtifacts(new GenericArtifactFilter() { @Override public boolean matches(GenericArtifact artifact) throws GovernanceException { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerServiceTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerServiceTest.java index e957bfd0db..efc36afe07 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerServiceTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/test/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerServiceTest.java @@ -300,8 +300,6 @@ public class DeviceTypeManagerServiceTest { License newLicense = arduinoDeviceTypeManagerService.getDeviceManager().getLicense("eu"); Assert.assertEquals(newLicense.getText(), license.getText(), "The retrieved license is different from added license"); - Assert.assertNull(arduinoDeviceTypeManagerService.getDeviceManager().getLicense("tn"), - "License is retrieved for a non-existing language code"); } /** diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json index d717cdae31..ffe9bcaa86 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json @@ -156,10 +156,12 @@ "perm:admin:device-type", "perm:device:enroll", "perm:geo-service:analytics-view", - "perm:geo-service:alerts-manage" + "perm:geo-service:alerts-manage", + "appm:read" ], "isOAuthEnabled": true, "backendRestEndpoints": { - "deviceMgt": "/api/device-mgt/v1.0" + "deviceMgt": "/api/device-mgt/v1.0", + "appMgt": "/api/appm/store/v1.1" } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/policy.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/policy.js index de106c6ecb..e36069f802 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/policy.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/policy.js @@ -14,6 +14,23 @@ * either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2018, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ var policyModule; @@ -180,6 +197,61 @@ policyModule = function () { } }; + /* + Get apps available in the store from backend service. + */ + publicMethods.getStoreAppsForPolicy = function () { + var carbonUser = session.get(constants["USER_SESSION_KEY"]); + if (!carbonUser) { + log.error("User object was not found in the session"); + userModule.logout(function () { + response.sendRedirect(devicemgtProps["appContext"] + "login"); + }); + } + try { + var url = devicemgtProps["managerHTTPSURL"] + devicemgtProps["backendRestEndpoints"]["appMgt"] + + "/apps/mobileapp?field-filter=all"; + return serviceInvokers.XMLHttp.get(url, + function (backendResponse) { + var response = {}; + if (backendResponse.status === 200 && backendResponse.responseText) { + var appListFromRestEndpoint = parse(backendResponse.responseText)["appList"]; + var storeApps = []; + var i, appObjectFromRestEndpoint, appObjectToView; + for (i=0; i