Merge branch 'master' of gitlab.com:entgra/carbon-device-mgt

merge-requests/38/head
lasanthaDLPDS 6 years ago
commit e852c62663

@ -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.

@ -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<String> deviceList);
}

@ -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<String> 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<String> 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();
}
}

@ -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<String> getDeviceIdentifiers(String type, String status, int tenantId) throws DeviceManagementDAOException;
boolean setEnrolmentStatusInBulk(String deviceType, String status, int tenantId, List<String> devices) throws DeviceManagementDAOException;
/**
* This method is used to retrieve the device count of a given tenant.
*

@ -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<String> getDeviceIdentifiers(String type, String status, int tenantId) throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<String> 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<String> 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);
}

@ -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";
}

@ -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<Device> 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<Device> authorizedDevices(List<Device> devices) throws SearchMgtException {
List<Device> 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<Device> getUpdatedDevices(long epochTime) throws SearchMgtException {
@ -256,7 +231,6 @@ public class ProcessorImpl implements Processor {
PreparedStatement stmt = null;
ResultSet rs = null;
List<Device> devices = new ArrayList<>();
Map<Integer, Integer> 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);

@ -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" +

@ -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<Device> aggregate(Map<String, List<Device>> devices) {
Map<Integer, Device> generalQueryMap = this.convertToMap(devices.get(Constants.GENERAL));
Map<Integer, Device> andMap = this.convertToMap(devices.get(Constants.PROP_AND));
Map<Integer, Device> orMap = this.convertToMap(devices.get(Constants.PROP_OR));
Map<Integer, Device> locationMap = this.convertToMap(devices.get(Constants.LOCATION));
Map<Integer, Device> finalMap = new HashMap<>();
List<Device> finalResult = new ArrayList<>();
List<Device> 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<Integer, Device> convertToMap(List<Device> devices) {
@ -79,7 +103,7 @@ public class ResultSetAggregatorImpl implements ResultSetAggregator {
}
Map<Integer, Device> 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);
}
}

@ -17,16 +17,7 @@
*/
package org.wso2.carbon.device.mgt.core.service;
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.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
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.*;
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;
@ -465,6 +456,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<Integer, Device> getTenantedDevice(DeviceIdentifier deviceIdentifier) throws DeviceManagementException;
void sendEnrolmentInvitation(String templateName, EmailMetaInfo metaInfo) throws DeviceManagementException,
@ -637,4 +651,10 @@ public interface DeviceManagementProviderService {
List<GeoCluster> findGeoClusters(String deviceType, GeoCoordinate southWest, GeoCoordinate northEast,
int geohashLength) throws DeviceManagementException;
int getDeviceCountOfTypeByStatus(String deviceType, String deviceStatus) throws DeviceManagementException;
List<String> getDeviceIdentifiersByStatus(String deviceType, String deviceStatus) throws DeviceManagementException;
boolean bulkUpdateDeviceStatus(String deviceType, List<String> deviceList, String status) throws DeviceManagementException;
}

@ -1959,6 +1959,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<Device> getDevicesByNameAndType(PaginationRequest request, boolean requireDeviceInfo)
throws DeviceManagementException {
@ -2708,6 +2759,67 @@ 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<String> getDeviceIdentifiersByStatus(String deviceType, String deviceStatus) throws DeviceManagementException {
int tenantId = this.getTenantId();
List<String> 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<String> deviceList, String status) throws DeviceManagementException {
int tenantId = this.getTenantId();
boolean success;
try {
DeviceManagementDAOFactory.openConnection();
success = deviceDAO.setEnrolmentStatusInBulk(deviceType, status, tenantId, deviceList);
} 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<Device.Property> properties = device.getProperties();
if (properties != null) {

@ -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<DeviceIdentifier> 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<Condition> 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<Device> 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<Condition> 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<Device> searchedDevices = processor.execute(context);
Assert.assertEquals(0, searchedDevices.size());
List<Device> 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<Condition> 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<Device> 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);
}
}

@ -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"})

@ -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"
}
}

@ -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,55 @@ 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<appListFromRestEndpoint.length; i++) {
appObjectFromRestEndpoint = appListFromRestEndpoint[i];
appObjectToView = {};
appObjectToView["appName"] = appObjectFromRestEndpoint["name"];
appObjectToView["appId"] = appObjectFromRestEndpoint["id"];
appObjectToView["packageName"] = appObjectFromRestEndpoint["appmeta"]["package"];
appObjectToView["version"] = appObjectFromRestEndpoint["version"];
appObjectToView["platform"] = appObjectFromRestEndpoint["platform"];
storeApps.push(appObjectToView);
}
response.status = "success";
response.content = storeApps;
return response;
} else {
response.status = "error";
if (backendResponse.responseText === "Scope validation failed") {
response.content = "Permission Denied";
} else {
response.content = backendResponse.responseText;
}
return response;
}
});
} catch (e) {
throw e;
}
};
/*
@Updated - used by getAllPolicies
*/

@ -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.
}}
{{unit "cdmf.unit.ui.title" pageTitle="Policy Management | Add Policy"}}
@ -40,4 +57,5 @@
{{#zone "content"}}
{{unit "cdmf.unit.device.operation-mod"}}
{{unit "cdmf.unit.policy.create"}}
{{unit "cdmf.unit.lib.data-table"}}
{{/zone}}

@ -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.
}}
{{unit "cdmf.unit.ui.title" pageTitle="Policy Management | Edit Policy"}}
@ -40,4 +57,5 @@
{{#zone "content"}}
{{unit "cdmf.unit.device.operation-mod"}}
{{unit "cdmf.unit.policy.edit"}}
{{unit "cdmf.unit.lib.data-table"}}
{{/zone}}

@ -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.
}}
{{unit "cdmf.unit.ui.title" pageTitle="Policy Management | View Policy"}}
@ -48,4 +65,5 @@
{{#zone "content"}}
{{unit "cdmf.unit.device.operation-mod"}}
{{unit "cdmf.unit.policy.view"}}
{{unit "cdmf.unit.lib.data-table"}}
{{/zone}}

@ -1,7 +1,9 @@
{{#zone "content"}}
{{#if isAuthorized}}
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}" data-isDeviceOwnerEnabled="{{isDeviceOwnerEnabled}}"></span>
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"
data-isDeviceOwnerEnabled="{{isDeviceOwnerEnabled}}" data-storeapps="{{storeApps}}">
</span>
<div class="row">
<div class="col-md-12">

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 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.
*/
function onRequest(context) {
@ -24,6 +41,7 @@ function onRequest(context) {
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
var policyModule = require("/app/modules/business-controllers/policy.js")["policyModule"];
var types = {};
types.isAuthorized = userModule.isAuthorized("/permission/admin/device-mgt/policies/manage");
@ -97,6 +115,8 @@ function onRequest(context) {
types["isCloud"] = devicemgtProps.isCloud;
types["isDeviceOwnerEnabled"] = devicemgtProps.isDeviceOwnerEnabled;
var enrollmentApps = policyModule.getStoreAppsForPolicy();
types["storeApps"] = JSON.stringify(enrollmentApps["content"]);
return types;
}

@ -13,6 +13,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 stepForwardFrom = {};
@ -145,8 +162,10 @@ stepForwardFrom["policy-platform"] = function (actionButton) {
var policyOperationsTemplateCacheKey = deviceType + '-policy-operations';
if (policyOperationsTemplateSrc) {
var storeApps = getStoreApps($("#logged-in-user").data("storeapps"), deviceType);
$.template(policyOperationsTemplateCacheKey, context + policyOperationsTemplateSrc, function (template) {
var content = template({"iscloud" : $("#logged-in-user").data("iscloud"), "isDeviceOwnerEnabled" : $("#logged-in-user").data("isdeviceownerenabled")});
var content = template({"iscloud" : $("#logged-in-user").data("iscloud"),
"isDeviceOwnerEnabled" : $("#logged-in-user").data("isdeviceownerenabled"), "storeapps" : storeApps});
$("#device-type-policy-operations").html(content).removeClass("hidden");
$(".policy-platform").addClass("hidden");
});
@ -172,6 +191,24 @@ stepForwardFrom["policy-platform"] = function (actionButton) {
$(".wr-advance-operations-init").addClass("hidden");
};
/**
* Retrieve store apps of the given device type
*
* @param storeApps
* @param deviceType
* @returns {Array}
*/
function getStoreApps(storeApps, deviceType) {
var selectedApps = [];
var i;
for (i=0; i<storeApps.length; i++) {
if (deviceType === storeApps[i].platform) {
selectedApps.push(storeApps[i]);
}
}
return selectedApps;
}
/**
* Forward action of policy profile page. Generates policy profile payload.
*/

@ -1,7 +1,7 @@
{{#zone "content"}}
{{#if isAuthorized }}
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"></span>
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}" data-storeapps="{{storeApps}}"></span>
<span id="policy-operations" class="hidden" data-template="{{policyOperations.template}}"
data-script="{{policyOperations.script}}" data-style="{{policyOperations.style}}"></span>
<div class="row">

@ -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.
*/
function onRequest(context) {
@ -21,6 +38,7 @@ function onRequest(context) {
var utility = require("/app/modules/utility.js").utility;
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
var policyModule = require("/app/modules/business-controllers/policy.js")["policyModule"];
var rolesResult = userModule.getRoles();
if (rolesResult.status == "success") {
@ -63,5 +81,8 @@ function onRequest(context) {
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
context["isCloud"] = devicemgtProps.isCloud;
var enrollmentApps = policyModule.getStoreAppsForPolicy();
context["storeApps"] = JSON.stringify(enrollmentApps["content"]);
return context;
}

@ -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 validateStep = {};
@ -202,7 +219,8 @@ skipStep["policy-platform"] = function (policyPayloadObj) {
hasPolicyProfileScript = false;
}
$.template(policyEditTemplateCacheKey, context + policyEditTemplateSrc, function (template) {
var content = template({"iscloud" : $("#logged-in-user").data("iscloud")});
var storeApps = getStoreApps($("#logged-in-user").data("storeapps"), deviceType);
var content = template({"iscloud" : $("#logged-in-user").data("iscloud"), "storeapps" : storeApps});
$("#device-type-policy-operations").html(content).removeClass("hidden");
$(".policy-platform").addClass("hidden");
if (hasPolicyProfileScript) {
@ -230,6 +248,24 @@ skipStep["policy-platform"] = function (policyPayloadObj) {
}
};
/**
* Retrieve store apps of the given device type
*
* @param storeApps
* @param deviceType
* @returns {Array}
*/
function getStoreApps(storeApps, deviceType) {
var selectedApps = [];
var i;
for (i=0; i<storeApps.length; i++) {
if (storeApps[i].platform === deviceType) {
selectedApps.push(storeApps[i]);
}
}
return selectedApps;
}
/**
* Forward action of policy profile page. Generates policy profile payload.
*/

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 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.
*/
@ -123,71 +140,69 @@ public class ComplianceDecisionPointImpl implements ComplianceDecisionPoint {
public void reEnforcePolicy(DeviceIdentifier deviceIdentifier, NonComplianceData complianceData) throws
PolicyComplianceException {
try {
Policy policy = complianceData.getPolicy();
if (policy != null) {
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<DeviceIdentifier>();
deviceIdentifiers.add(deviceIdentifier);
List<ProfileOperation> profileOperationList = new ArrayList<ProfileOperation>();
PolicyOperation policyOperation = new PolicyOperation();
policyOperation.setEnabled(true);
policyOperation.setType(Operation.Type.POLICY);
policyOperation.setCode(PolicyOperation.POLICY_OPERATION_CODE);
if (complianceData.isCompletePolicy()) {
List<ProfileFeature> effectiveFeatures = policy.getProfile().getProfileFeaturesList();
for (ProfileFeature feature : effectiveFeatures) {
ProfileOperation profileOperation = new ProfileOperation();
profileOperation.setCode(feature.getFeatureCode());
profileOperation.setEnabled(true);
profileOperation.setStatus(Operation.Status.PENDING);
profileOperation.setType(Operation.Type.PROFILE);
profileOperation.setPayLoad(feature.getContent());
profileOperationList.add(profileOperation);
}
} else {
List<ComplianceFeature> noneComplianceFeatures = complianceData.getComplianceFeatures();
List<ProfileFeature> effectiveFeatures = policy.getProfile().getProfileFeaturesList();
for (ComplianceFeature feature : noneComplianceFeatures) {
for (ProfileFeature pf : effectiveFeatures) {
if (pf.getFeatureCode().equalsIgnoreCase(feature.getFeatureCode())) {
ProfileOperation profileOperation = new ProfileOperation();
profileOperation.setCode(feature.getFeatureCode());
profileOperation.setEnabled(true);
profileOperation.setStatus(Operation.Status.PENDING);
profileOperation.setType(Operation.Type.PROFILE);
profileOperation.setPayLoad(pf.getContent());
profileOperationList.add(profileOperation);
// do not re-enforce policy if the only feature to be applied is enrollment app install
if (complianceData.getComplianceFeatures().size() != 1 || !PolicyManagementConstants
.ENROLLMENT_APP_INSTALL_FEATURE_CODE.equals(complianceData.getComplianceFeatures().get(0)
.getFeatureCode())) {
try {
Policy policy = complianceData.getPolicy();
if (policy != null) {
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(deviceIdentifier);
List<ProfileOperation> profileOperationList = new ArrayList<>();
PolicyOperation policyOperation = new PolicyOperation();
policyOperation.setEnabled(true);
policyOperation.setType(Operation.Type.POLICY);
policyOperation.setCode(PolicyOperation.POLICY_OPERATION_CODE);
if (complianceData.isCompletePolicy()) {
List<ProfileFeature> effectiveFeatures = policy.getProfile().getProfileFeaturesList();
for (ProfileFeature feature : effectiveFeatures) {
ProfileOperation profileOperation = new ProfileOperation();
profileOperation.setCode(feature.getFeatureCode());
profileOperation.setEnabled(true);
profileOperation.setStatus(Operation.Status.PENDING);
profileOperation.setType(Operation.Type.PROFILE);
profileOperation.setPayLoad(feature.getContent());
profileOperationList.add(profileOperation);
}
} else {
List<ComplianceFeature> noneComplianceFeatures = complianceData.getComplianceFeatures();
List<ProfileFeature> effectiveFeatures = policy.getProfile().getProfileFeaturesList();
for (ComplianceFeature feature : noneComplianceFeatures) {
for (ProfileFeature pf : effectiveFeatures) {
if (pf.getFeatureCode().equalsIgnoreCase(feature.getFeatureCode())) {
ProfileOperation profileOperation = new ProfileOperation();
profileOperation.setCode(feature.getFeatureCode());
profileOperation.setEnabled(true);
profileOperation.setStatus(Operation.Status.PENDING);
profileOperation.setType(Operation.Type.PROFILE);
profileOperation.setPayLoad(pf.getContent());
profileOperationList.add(profileOperation);
}
}
}
}
}
policyOperation.setProfileOperations(profileOperationList);
policyOperation.setPayLoad(policyOperation.getProfileOperations());
policyOperation.setProfileOperations(profileOperationList);
policyOperation.setPayLoad(policyOperation.getProfileOperations());
//TODO: Fix this properly later adding device type to be passed in when the task manage executes "addOperations()"
String type = null;
if (deviceIdentifiers.size() > 0) {
type = deviceIdentifiers.get(0).getType();
}
PolicyManagementDataHolder.getInstance().getDeviceManagementService().
addOperation(type, policyOperation, deviceIdentifiers);
//TODO: Fix this properly later adding device type to be passed in when the task manage executes "addOperations()"
String type = null;
if (deviceIdentifiers.size() > 0) {
type = deviceIdentifiers.get(0).getType();
}
PolicyManagementDataHolder.getInstance().getDeviceManagementService().
addOperation(type, policyOperation, deviceIdentifiers);
}
} catch (InvalidDeviceException e) {
throw new PolicyComplianceException("Invalid Device identifiers found.", e);
} catch (OperationManagementException e) {
throw new PolicyComplianceException("Error occurred while re-enforcing the policy to device " + deviceIdentifier.getId() + " - " +
deviceIdentifier.getType(), e);
}
} catch (InvalidDeviceException e) {
throw new PolicyComplianceException("Invalid Device identifiers found.", e);
} catch (OperationManagementException e) {
throw new PolicyComplianceException("Error occurred while re-enforcing the policy to device " + deviceIdentifier.getId() + " - " +
deviceIdentifier.getType(), e);
}
}

@ -31,6 +31,8 @@ public final class PolicyManagementConstants {
public static final String WARN = "WARN";
public static final String BLOCK = "BLOCK";
public static final String ENROLLMENT_APP_INSTALL_FEATURE_CODE = "ENROLLMENT_APP_INSTALL";
public static final String MONITORING_TASK_TYPE = "MONITORING_TASK";
public static final String MONITORING_TASK_NAME = "MONITORING";
public static final String MONITORING_TASK_CLAZZ = "org.wso2.carbon.policy.mgt.core.task.MonitoringTask";

Loading…
Cancel
Save