Merge branch 'corrective-policy' of https://gitlab.com/entgra/carbon-device-mgt into corrective-policy

corrective-policy
Pahansith 4 years ago
commit 7756b6c16d

@ -173,14 +173,14 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
if (deviceTypeId != -1) { if (deviceTypeId != -1) {
sql += "AND AP_APP.DEVICE_TYPE_ID = ? "; sql += "AND AP_APP.DEVICE_TYPE_ID = ? ";
} }
sql += "GROUP BY AP_APP.ID "; sql += "GROUP BY AP_APP.ID ORDER BY AP_APP.ID ";
if (StringUtils.isNotEmpty(filter.getSortBy())) { if (StringUtils.isNotEmpty(filter.getSortBy())) {
sql += "ORDER BY ID " + filter.getSortBy() +" "; sql += filter.getSortBy() +" ";
} }
if (filter.getLimit() != -1) { if (filter.getLimit() != -1) {
sql += "LIMIT ? OFFSET ? "; sql += "LIMIT ? OFFSET ? ";
} }
sql += ") AS app_data ON app_data.ID = AP_APP.ID WHERE AP_APP.TENANT_ID = ?"; sql += ") AS app_data ON app_data.ID = AP_APP.ID WHERE AP_APP.TENANT_ID = ? ORDER BY AP_APP.ID";
try { try {
Connection conn = this.getDBConnection(); Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql)) {

@ -118,15 +118,14 @@ public class OracleApplicationDAOImpl extends GenericApplicationDAOImpl {
if (deviceTypeId != -1) { if (deviceTypeId != -1) {
sql += "AND AP_APP.DEVICE_TYPE_ID = ? "; sql += "AND AP_APP.DEVICE_TYPE_ID = ? ";
} }
sql += "GROUP BY AP_APP.ID "; sql += "GROUP BY AP_APP.ID ORDER BY AP_APP.ID ";
if (StringUtils.isNotEmpty(filter.getSortBy())) { if (StringUtils.isNotEmpty(filter.getSortBy())) {
sql += "ORDER BY ID " + filter.getSortBy() + " "; sql += filter.getSortBy() +" ";
} }
if (filter.getLimit() != -1) { if (filter.getLimit() != -1) {
sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY "; sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
} }
sql += ") AS app_data ON app_data.ID = AP_APP.ID " + sql += ") AS app_data ON app_data.ID = AP_APP.ID WHERE AP_APP.TENANT_ID = ? ORDER BY AP_APP.ID";
"WHERE AP_APP.TENANT_ID = ?";
try { try {
Connection conn = this.getDBConnection(); Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql)) {

@ -117,15 +117,14 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
if (deviceTypeId != -1) { if (deviceTypeId != -1) {
sql += "AND AP_APP.DEVICE_TYPE_ID = ? "; sql += "AND AP_APP.DEVICE_TYPE_ID = ? ";
} }
sql += "GROUP BY AP_APP.ID "; sql += "GROUP BY AP_APP.ID ORDER BY AP_APP.ID ";
if (StringUtils.isNotEmpty(filter.getSortBy())) { if (StringUtils.isNotEmpty(filter.getSortBy())) {
sql += "ORDER BY ID " + filter.getSortBy() + " "; sql += filter.getSortBy() +" ";
} }
if (filter.getLimit() != -1) { if (filter.getLimit() != -1) {
sql += "ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY "; sql += "ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
} }
sql += ") AS app_data ON app_data.ID = AP_APP.ID " + sql += ") AS app_data ON app_data.ID = AP_APP.ID WHERE AP_APP.TENANT_ID = ? ORDER BY AP_APP.ID";
"WHERE AP_APP.TENANT_ID = ?";
try { try {
Connection conn = this.getDBConnection(); Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql)) {

@ -393,6 +393,96 @@ public interface DeviceManagementService {
@QueryParam("limit") @QueryParam("limit")
int limit); int limit);
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{groupId}/location-history")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting the Location Details of Devices in the group",
notes = "Get the location details of devices in the group during a define time period.",
response = Response.class,
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 = 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 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 Location history details for the devices with the specified group id was not found.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the devices location history details.",
response = ErrorResponse.class)
})
Response getDevicesGroupLocationInfo(
@ApiParam(
name = "groupId",
value = "The group ID.",
required = true)
@PathParam("groupId") int groupId,
@ApiParam(
name = "from",
value = "Define the time to start getting the geo location history of the device in " +
"milliseconds.",
required = true)
@QueryParam("from") long from,
@ApiParam(
name = "to",
value = "Define the time to finish getting the geo location history of the device in " +
"milliseconds.",
required = true)
@QueryParam("to") long to,
@ApiParam(
name = "type",
value = "Defines how the output should be.",
required = true)
@QueryParam("type") String type,
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items.",
required = false,
defaultValue = "0")
@QueryParam("offset") int offset,
@ApiParam(
name = "limit",
value = "Provide how many device details you require from the starting pagination index/offset.",
required = false,
defaultValue = "100")
@QueryParam("limit") int limit
);
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}") @Path("/{type}/{id}")

@ -36,9 +36,6 @@
package org.wso2.carbon.device.mgt.jaxrs.service.impl; package org.wso2.carbon.device.mgt.jaxrs.service.impl;
import java.util.LinkedList;
import java.util.Queue;
import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -51,8 +48,6 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.Feature; import org.wso2.carbon.device.mgt.common.Feature;
import org.wso2.carbon.device.mgt.common.FeatureManager; import org.wso2.carbon.device.mgt.common.FeatureManager;
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.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.Application;
@ -62,15 +57,13 @@ import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorization
import org.wso2.carbon.device.mgt.common.device.details.DeviceData; import org.wso2.carbon.device.mgt.common.device.details.DeviceData;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; 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.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshot;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidConfigurationException; import org.wso2.carbon.device.mgt.common.exceptions.InvalidConfigurationException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.exceptions.UnAuthorizedException;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
@ -92,6 +85,7 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService;
import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException; import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceCompliance; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceCompliance;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList;
@ -112,7 +106,6 @@ import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerSer
import org.wso2.carbon.policy.mgt.common.PolicyManagementException; import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService; import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.validation.Valid; import javax.validation.Valid;
@ -219,29 +212,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
if (groupId != 0) { if (groupId != 0) {
try { try {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); boolean isPermitted = DeviceMgtAPIUtils.checkPermission(groupId, authorizedUser);
UserStoreManager userStoreManager = DeviceMgtAPIUtils.getRealmService()
.getTenantUserRealm(tenantId).getUserStoreManager();
String[] userRoles = userStoreManager.getRoleListOfUser(authorizedUser);
boolean isPermitted = false;
if (deviceAccessAuthorizationService.isDeviceAdminUser()) {
isPermitted = true;
} else {
List<String> roles = DeviceMgtAPIUtils.getGroupManagementProviderService().getRoles(groupId);
for (String userRole : userRoles) {
if (roles.contains(userRole)) {
isPermitted = true;
break;
}
}
if (!isPermitted) {
DeviceGroup deviceGroup = DeviceMgtAPIUtils.getGroupManagementProviderService()
.getGroup(groupId, false);
if (deviceGroup != null && authorizedUser.equals(deviceGroup.getOwner())) {
isPermitted = true;
}
}
}
if (isPermitted) { if (isPermitted) {
request.setGroupId(groupId); request.setGroupId(groupId);
} else { } else {
@ -384,6 +355,103 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
} }
} }
/**
* Validate group Id and group Id greater than 0 and exist.
*
* @param groupId Group ID of the group
* @param from time to start getting DeviceLocationHistorySnapshotWrapper in milliseconds
* @param to time to end getting DeviceLocationHistorySnapshotWrapper in milliseconds
*/
private static void validateGroupId(int groupId, long from, long to) throws GroupManagementException, BadRequestException {
if (from == 0 || to == 0) {
String msg = "Invalid values for from/to";
log.error(msg);
throw new BadRequestException(msg);
}
if (groupId <= 0) {
String msg = "Invalid group ID '" + groupId + "'";
log.error(msg);
throw new BadRequestException(msg);
}
GroupManagementProviderService service = DeviceMgtAPIUtils.getGroupManagementProviderService();
if (service.getGroup(groupId, false) == null) {
String msg = "Invalid group ID '" + groupId + "'";
log.error(msg);
throw new BadRequestException(msg);
}
}
@GET
@Override
@Path("/{groupId}/location-history")
public Response getDevicesGroupLocationInfo(@PathParam("groupId") int groupId,
@QueryParam("from") long from,
@QueryParam("to") long to,
@QueryParam("type") String type,
@DefaultValue("0") @QueryParam("offset") int offset,
@DefaultValue("100") @QueryParam("limit") int limit){
try {
RequestValidationUtil.validatePaginationParameters(offset, limit);
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
PaginationRequest request = new PaginationRequest(offset, limit);
DeviceList devices = new DeviceList();
// this is the user who initiates the request
String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername();
try {
validateGroupId(groupId, from, to);
boolean isPermitted = DeviceMgtAPIUtils.checkPermission(groupId, authorizedUser);
if (isPermitted) {
request.setGroupId(groupId);
} else {
String msg = "Current user '" + authorizedUser
+ "' doesn't have enough privileges to list devices of group '"
+ groupId + "'";
log.error(msg);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
}
} catch (GroupManagementException e) {
String msg = "Error occurred while getting the data using '" + groupId + "'";
log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (UserStoreException e){
String msg = "Error occurred while retrieving role list of user '" + authorizedUser + "'";
log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
PaginationResult result = dms.getAllDevices(request, false);
if(!result.getData().isEmpty()){
devices.setList((List<Device>) result.getData());
for (Device device : devices.getList()) {
DeviceLocationHistorySnapshotWrapper snapshotWrapper = DeviceMgtAPIUtils.getDeviceHistorySnapshots(
device.getType(), device.getDeviceIdentifier(), authorizedUser, from, to, type,
dms);
device.setHistorySnapshot(snapshotWrapper);
}
}
return Response.status(Response.Status.OK).entity(devices).build();
} catch (BadRequestException e) {
String msg = "Invalid type, use either 'path' or 'full'";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (UnAuthorizedException e) {
String msg = "Current user doesn't have enough privileges to list devices of group '" + groupId + "'";
log.error(msg, e);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
} catch (DeviceManagementException e) {
String msg = "Error occurred while fetching the device information.";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (DeviceAccessAuthorizationException e) {
String msg = "Error occurred while checking device access authorization";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
@DELETE @DELETE
@Override @Override
@Path("/type/{deviceType}/id/{deviceId}") @Path("/type/{deviceType}/id/{deviceId}")
@ -514,115 +582,33 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@QueryParam("to") long to, @QueryParam("to") long to,
@QueryParam("type") String type) { @QueryParam("type") String type) {
try { try {
RequestValidationUtil.validateDeviceIdentifier(deviceType, deviceId);
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
DeviceAccessAuthorizationService deviceAccessAuthorizationService =
DeviceMgtAPIUtils.getDeviceAccessAuthorizationService();
String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername(); String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername();
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId, deviceType); DeviceLocationHistorySnapshotWrapper snapshotWrapper = DeviceMgtAPIUtils.getDeviceHistorySnapshots(
deviceType, deviceId, authorizedUser, from, to, type,
if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser)) { dms);
String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" +
deviceId + "'";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorResponse.ErrorResponseBuilder()
.setCode(Response.Status.UNAUTHORIZED.getStatusCode()).setMessage(msg).build()).build();
}
if (from == 0 || to == 0) {
String msg = "Invalid values for from/to";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorResponse.ErrorResponseBuilder()
.setCode(Response.Status.BAD_REQUEST.getStatusCode()).setMessage(msg)).build();
}
// Get the location history snapshots for the given period
List<DeviceLocationHistorySnapshot> deviceLocationHistorySnapshots = dms
.getDeviceLocationInfo(deviceIdentifier, from, to);
OperationMonitoringTaskConfig operationMonitoringTaskConfig = dms.getDeviceMonitoringConfig(deviceType);
int taskFrequency = operationMonitoringTaskConfig.getFrequency();
int operationRecurrentTimes = 0;
List<MonitoringOperation> monitoringOperations = operationMonitoringTaskConfig.getMonitoringOperation();
for (MonitoringOperation monitoringOperation : monitoringOperations) {
if (monitoringOperation.getTaskName().equals("DEVICE_LOCATION")) {
operationRecurrentTimes = monitoringOperation.getRecurrentTimes();
break;
}
}
// Device Location operation frequency in milliseconds. Adding 100000 ms as an error
long operationFrequency = taskFrequency * operationRecurrentTimes + 100000;
Queue<DeviceLocationHistorySnapshot> deviceLocationHistorySnapshotsQueue = new LinkedList<>(
deviceLocationHistorySnapshots);
List<List<DeviceLocationHistorySnapshot>> locationHistorySnapshotList = new ArrayList<>();
List<Object> pathsArray = new ArrayList<>();
DeviceLocationHistorySnapshotWrapper snapshotWrapper = new DeviceLocationHistorySnapshotWrapper();
while (!deviceLocationHistorySnapshotsQueue.isEmpty()) {
List<DeviceLocationHistorySnapshot> snapshots = new ArrayList<>();
// Make a copy of remaining snapshots
List<DeviceLocationHistorySnapshot> cachedSnapshots = new ArrayList<>(
deviceLocationHistorySnapshotsQueue);
List<Object> locationPoint = new ArrayList<>();
for (int i = 0; i < cachedSnapshots.size(); i++) {
DeviceLocationHistorySnapshot currentSnapshot = deviceLocationHistorySnapshotsQueue.poll();
snapshots.add(currentSnapshot);
if (currentSnapshot != null) {
locationPoint.add(currentSnapshot.getLatitude());
locationPoint.add(currentSnapshot.getLongitude());
locationPoint.add(currentSnapshot.getUpdatedTime());
pathsArray.add(new ArrayList<>(locationPoint));
locationPoint.clear();
}
if (!deviceLocationHistorySnapshotsQueue.isEmpty()) {
DeviceLocationHistorySnapshot nextSnapshot = deviceLocationHistorySnapshotsQueue.peek();
locationPoint.add(nextSnapshot.getLatitude());
locationPoint.add(nextSnapshot.getLongitude());
locationPoint.add(nextSnapshot.getUpdatedTime());
pathsArray.add(new ArrayList<>(locationPoint));
locationPoint.clear();
if (nextSnapshot.getUpdatedTime().getTime() - currentSnapshot.getUpdatedTime().getTime()
> operationFrequency) {
break;
}
}
}
locationHistorySnapshotList.add(snapshots);
}
DeviceLocationHistory deviceLocationHistory = new DeviceLocationHistory();
deviceLocationHistory.setLocationHistorySnapshots(locationHistorySnapshotList);
if (type != null) {
if (type.equals("path")) {
snapshotWrapper.setPathSnapshot(pathsArray);
} else if (type.equals("full")) {
snapshotWrapper.setFullSnapshot(deviceLocationHistory);
} else {
String msg = "Invalid type, use either 'path' or 'full'";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorResponse.ErrorResponseBuilder()
.setCode(Response.Status.BAD_REQUEST.getStatusCode()).setMessage(msg)).build();
}
} else {
snapshotWrapper.setFullSnapshot(deviceLocationHistory);
}
return Response.status(Response.Status.OK).entity(snapshotWrapper).build(); return Response.status(Response.Status.OK).entity(snapshotWrapper).build();
} catch (BadRequestException e) {
String msg = "Invalid type, use either 'path' or 'full'";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (UnAuthorizedException e) {
String msg = "Current user doesn't have enough privileges to retrieve the given device id '"
+ deviceId + "'";
log.error(msg, e);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
String msg = "Error occurred while fetching the device information."; String msg = "Error occurred while fetching the device information.";
log.error(msg, e); log.error(msg, e);
return Response.serverError().entity(new ErrorResponse.ErrorResponseBuilder() return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
.setCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).setMessage(msg).build()).build();
} catch (DeviceAccessAuthorizationException e) {
String msg = "Error occurred while checking the device authorization.";
log.error(msg, e);
return Response.serverError().entity(new ErrorResponse.ErrorResponseBuilder()
.setCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).setMessage(msg).build()).build();
} catch (InputValidationException e) { } catch (InputValidationException e) {
String msg = "Invalid device Id or device type"; String msg = "Invalid device Id or device type";
log.error(msg, e); log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorResponse.ErrorResponseBuilder() return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
.setCode(Response.Status.BAD_REQUEST.getStatusCode()).setMessage(msg)).build(); } catch (DeviceAccessAuthorizationException e) {
String msg = "Error occurred while checking device access authorization";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} }
} }

@ -53,16 +53,25 @@ import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService; import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.common.MonitoringOperation;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshot;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper;
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
import org.wso2.carbon.device.mgt.common.exceptions.UnAuthorizedException;
import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService; import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.metadata.mgt.MetadataManagementService; import org.wso2.carbon.device.mgt.common.metadata.mgt.MetadataManagementService;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
@ -82,6 +91,7 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean; import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList; import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub; import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub;
import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub; import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub;
import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub; import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub;
@ -123,7 +133,9 @@ import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue;
/** /**
* MDMAPIUtils class provides utility function used by CDM REST-API classes. * MDMAPIUtils class provides utility function used by CDM REST-API classes.
@ -940,4 +952,149 @@ public class DeviceMgtAPIUtils {
claimPropertyDTO.setPropertyValue(propertyValue); claimPropertyDTO.setPropertyValue(propertyValue);
return claimPropertyDTO; return claimPropertyDTO;
} }
/**
* Getting Device History Snapshots for given Device Type and Identifier.
*
* @param deviceType Device type of the device
* @param identifier Device identifier of the device
* @param authorizedUser user who initiates the request
* @param from time to start getting DeviceLocationHistorySnapshotWrapper in milliseconds
* @param to time to end getting DeviceLocationHistorySnapshotWrapper in milliseconds
* @param type output type should be for DeviceLocationHistorySnapshotWrapper
* @param dms DeviceManagementService instance
*
* @return DeviceLocationHistorySnapshotWrapper instance
* @throws DeviceManagementException if device information cannot be fetched
* @throws DeviceAccessAuthorizationException if device authorization get failed
*/
public static DeviceLocationHistorySnapshotWrapper getDeviceHistorySnapshots(String deviceType,
String identifier,
String authorizedUser,
long from,
long to,
String type,
DeviceManagementProviderService dms)
throws DeviceManagementException, DeviceAccessAuthorizationException {
RequestValidationUtil.validateDeviceIdentifier(deviceType, identifier);
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(identifier, deviceType);
if (!getDeviceAccessAuthorizationService().isUserAuthorized(deviceIdentifier, authorizedUser)) {
String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" +
identifier + "'";
log.error(msg);
throw new UnAuthorizedException(msg);
}
// Get the location history snapshots for the given period
List<DeviceLocationHistorySnapshot> deviceLocationHistorySnapshots = dms.getDeviceLocationInfo(deviceIdentifier, from, to);
OperationMonitoringTaskConfig operationMonitoringTaskConfig = dms.getDeviceMonitoringConfig(deviceType);
int taskFrequency = operationMonitoringTaskConfig.getFrequency();
int operationRecurrentTimes = 0;
List<MonitoringOperation> monitoringOperations = operationMonitoringTaskConfig.getMonitoringOperation();
for (MonitoringOperation monitoringOperation : monitoringOperations) {
if (monitoringOperation.getTaskName().equals("DEVICE_LOCATION")) {
operationRecurrentTimes = monitoringOperation.getRecurrentTimes();
break;
}
}
// Device Location operation frequency in milliseconds. Adding 100000 ms as an error
long operationFrequency = taskFrequency * operationRecurrentTimes + 100000;
Queue<DeviceLocationHistorySnapshot> deviceLocationHistorySnapshotsQueue = new LinkedList<>(
deviceLocationHistorySnapshots);
List<List<DeviceLocationHistorySnapshot>> locationHistorySnapshotList = new ArrayList<>();
List<Object> pathsArray = new ArrayList<>();
DeviceLocationHistorySnapshotWrapper snapshotWrapper = new DeviceLocationHistorySnapshotWrapper();
while (!deviceLocationHistorySnapshotsQueue.isEmpty()) {
List<DeviceLocationHistorySnapshot> snapshots = new ArrayList<>();
// Make a copy of remaining snapshots
List<DeviceLocationHistorySnapshot> cachedSnapshots = new ArrayList<>(
deviceLocationHistorySnapshotsQueue);
List<Object> locationPoint = new ArrayList<>();
for (int i = 0; i < cachedSnapshots.size(); i++) {
DeviceLocationHistorySnapshot currentSnapshot = deviceLocationHistorySnapshotsQueue.poll();
snapshots.add(currentSnapshot);
if (currentSnapshot != null) {
locationPoint.add(currentSnapshot.getLatitude());
locationPoint.add(currentSnapshot.getLongitude());
locationPoint.add(currentSnapshot.getUpdatedTime());
pathsArray.add(new ArrayList<>(locationPoint));
locationPoint.clear();
}
if (!deviceLocationHistorySnapshotsQueue.isEmpty()) {
DeviceLocationHistorySnapshot nextSnapshot = deviceLocationHistorySnapshotsQueue.peek();
locationPoint.add(nextSnapshot.getLatitude());
locationPoint.add(nextSnapshot.getLongitude());
locationPoint.add(nextSnapshot.getUpdatedTime());
pathsArray.add(new ArrayList<>(locationPoint));
locationPoint.clear();
if (nextSnapshot.getUpdatedTime().getTime() - currentSnapshot.getUpdatedTime().getTime()
> operationFrequency) {
break;
}
}
}
locationHistorySnapshotList.add(snapshots);
}
DeviceLocationHistory deviceLocationHistory = new DeviceLocationHistory();
deviceLocationHistory.setLocationHistorySnapshots(locationHistorySnapshotList);
if (type != null) {
if (type.equals("path")) {
snapshotWrapper.setPathSnapshot(pathsArray);
} else if (type.equals("full")) {
snapshotWrapper.setFullSnapshot(deviceLocationHistory);
} else {
String msg = "Invalid type, use either 'path' or 'full'";
log.error(msg);
throw new BadRequestException(msg);
}
} else {
snapshotWrapper.setFullSnapshot(deviceLocationHistory);
}
return snapshotWrapper;
}
/**
* Check user who initiates the request has permission to list devices from given group Id.
*
* @param groupId Group ID of the group
* @param authorizedUser user who initiates the request
*
* @return boolean instance
* @throws UserStoreException if roles list of authorizedUser cannot be fetched
* @throws DeviceAccessAuthorizationException if device authorization get failed.
* @throws GroupManagementException if group or roles cannot be fetched using groupId
*/
public static boolean checkPermission(int groupId, String authorizedUser) throws UserStoreException, DeviceAccessAuthorizationException, GroupManagementException {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
UserStoreManager userStoreManager = DeviceMgtAPIUtils.getRealmService()
.getTenantUserRealm(tenantId).getUserStoreManager();
String[] userRoles = userStoreManager.getRoleListOfUser(authorizedUser);
boolean isPermitted = false;
if (getDeviceAccessAuthorizationService().isDeviceAdminUser()) {
isPermitted = true;
} else {
List<String> roles = DeviceMgtAPIUtils.getGroupManagementProviderService().getRoles(groupId);
for (String userRole : userRoles) {
if (roles.contains(userRole)) {
isPermitted = true;
break;
}
}
if (!isPermitted) {
DeviceGroup deviceGroup = DeviceMgtAPIUtils.getGroupManagementProviderService()
.getGroup(groupId, false);
if (deviceGroup != null && authorizedUser.equals(deviceGroup.getOwner())) {
isPermitted = true;
}
}
}
return isPermitted;
}
} }

@ -20,8 +20,10 @@ package org.wso2.carbon.device.mgt.common;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@ -70,6 +72,12 @@ public class Device implements Serializable {
required = false) required = false)
private List<Application> applications; private List<Application> applications;
@ApiModelProperty(
name = "historySnapshot",
value = "device history snapshots")
@JsonProperty(value = "historySnapshot")
private DeviceLocationHistorySnapshotWrapper historySnapshot;
public Device() { public Device() {
} }
@ -164,6 +172,14 @@ public class Device implements Serializable {
this.applications = applications; this.applications = applications;
} }
public DeviceLocationHistorySnapshotWrapper getHistorySnapshot() {
return historySnapshot;
}
public void setHistorySnapshot(DeviceLocationHistorySnapshotWrapper historySnapshot) {
this.historySnapshot = historySnapshot;
}
public static class Property { public static class Property {
private String name; private String name;

@ -58,6 +58,7 @@ public class DeviceIdentifier implements Serializable{
public void setType(String type) { public void setType(String type) {
this.type = type.trim(); this.type = type.trim();
} }
public String getId() { public String getId() {
return id; return id;
} }

Loading…
Cancel
Save