Merge branch 'conflicts-fix' into 'application-mgt-new'

Create an APIs to get device details and the subscription details with given app installed

See merge request entgra/carbon-device-mgt!277
feature/appm-store/pbac
Dharmakeerthi Lasantha 5 years ago
commit a4f99c9c77

@ -0,0 +1,38 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.application.mgt.common;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
public class BasePaginatedResult {
@ApiModelProperty(
value = "Number of total resources.",
example = "1")
@JsonProperty("count")
private long count;
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}

@ -0,0 +1,87 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.application.mgt.common;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(value = "BasicUserInfo", description = "Basic user information and the roles of the user.")
public class BasicUserInfo {
@ApiModelProperty(name = "username", value = "The login name of the user.", required = true )
private String username;
@ApiModelProperty(name = "firstname", value = "The first name of the user.", required = true )
private String firstname;
@ApiModelProperty(name = "lastname", value = "The last name of the user.", required = true )
private String lastname;
@ApiModelProperty(name = "emailAddress", value = "The email address of the user.", required = true )
private String emailAddress;
@ApiModelProperty(name = "createdDate", value = "User creation date." )
private String createdDate;
@ApiModelProperty(name = "modifiedDate", value = "User modifiedDate date." )
private String modifiedDate;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
public String getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(String modifiedDate) {
this.modifiedDate = modifiedDate;
}
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.application.mgt.common;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
@ApiModel(value = "BasicUserInfoList", description = "This contains basic details of a set of users that matches " +
"a given criteria as a collection")
public class BasicUserInfoList extends BasePaginatedResult {
private List<BasicUserInfo> users = new ArrayList<>();
@ApiModelProperty(value = "List of devices returned")
@JsonProperty("users")
public List<BasicUserInfo> getList() {
return users;
}
public void setList(List<BasicUserInfo> users) {
this.users = users;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append(" count: ").append(getCount()).append(",\n");
sb.append(" users: [").append(users).append("\n");
sb.append("]}\n");
return sb.toString();
}
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.application.mgt.common;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
public class DeviceGroupList extends BasePaginatedResult {
@ApiModelProperty(value = "List of device groups returned")
@JsonProperty("groups")
private List<?> deviceGroups = new ArrayList<>();
public List<?> getList() {
return deviceGroups;
}
public void setList(List<?> deviceGroups) {
this.deviceGroups = deviceGroups;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append(" count: ").append(getCount()).append(",\n");
sb.append(" groups: [").append(deviceGroups).append("\n");
sb.append("]}\n");
return sb.toString();
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.application.mgt.common;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.wso2.carbon.device.mgt.common.Device;
import java.util.ArrayList;
import java.util.List;
public class DeviceList extends BasePaginatedResult {
private List<Device> devices = new ArrayList<>();
@ApiModelProperty(value = "List of devices returned")
@JsonProperty("devices")
public List<Device> getList() {
return devices;
}
public void setList(List<Device> devices) {
this.devices = devices;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append(" count: ").append(getCount()).append(",\n");
sb.append(" devices: [").append(devices).append("\n");
sb.append("]}\n");
return sb.toString();
}
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.application.mgt.common;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
@ApiModel(value = "Role List")
public class RoleList extends BasePaginatedResult {
private List<?> roles;
@ApiModelProperty(value = "Returns the list of roles that match the offset and limit parameter values "
+ "that were specified.")
@JsonProperty("roles")
public List<?> getList() {
return roles;
}
public void setList(List<?> roles) {
this.roles = roles;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append(" count: ").append(getCount()).append(",\n");
sb.append(" roles: [").append(roles).append("\n");
sb.append("]}\n");
return sb.toString();
}
}

@ -23,21 +23,22 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class SubscribingDeviceIdHolder { public class SubscribingDeviceIdHolder {
private Map<DeviceIdentifier, Integer> subscribedDevices = new HashMap<>(); private Map<DeviceIdentifier, Integer> appInstalledDevices = new HashMap<>();
private Map<DeviceIdentifier, Integer> subscribableDevices = new HashMap<>(); private Map<DeviceIdentifier, Integer> appInstallableDevices = new HashMap<>();
public Map<DeviceIdentifier, Integer> getSubscribedDevices() {
return subscribedDevices; public Map<DeviceIdentifier, Integer> getAppInstalledDevices() {
return appInstalledDevices;
} }
public void setSubscribedDevices(Map<DeviceIdentifier, Integer> subscribedDevices) { public void setAppInstalledDevices(Map<DeviceIdentifier, Integer> appInstalledDevices) {
this.subscribedDevices = subscribedDevices; this.appInstalledDevices = appInstalledDevices;
} }
public Map<DeviceIdentifier, Integer> getSubscribableDevices() { public Map<DeviceIdentifier, Integer> getAppInstallableDevices() {
return subscribableDevices; return appInstallableDevices;
} }
public void setSubscribableDevices(Map<DeviceIdentifier, Integer> subscribableDevices) { public void setAppInstallableDevices(Map<DeviceIdentifier, Integer> appInstallableDevices) {
this.subscribableDevices = subscribableDevices; this.appInstallableDevices = appInstallableDevices;
} }
} }

@ -23,6 +23,7 @@ import org.wso2.carbon.device.application.mgt.common.ExecutionStatus;
import org.wso2.carbon.device.application.mgt.common.dto.ScheduledSubscriptionDTO; import org.wso2.carbon.device.application.mgt.common.dto.ScheduledSubscriptionDTO;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.SubscriptionManagementException; import org.wso2.carbon.device.application.mgt.common.exception.SubscriptionManagementException;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import java.util.List; import java.util.List;
@ -83,4 +84,30 @@ public interface SubscriptionManager {
* @throws SubscriptionManagementException if error occurred while updating the status of the subscription * @throws SubscriptionManagementException if error occurred while updating the status of the subscription
*/ */
void updateScheduledSubscriptionStatus(int id, ExecutionStatus status) throws SubscriptionManagementException; void updateScheduledSubscriptionStatus(int id, ExecutionStatus status) throws SubscriptionManagementException;
/***
* This method used to get the app id ,device ids and pass them to DM service method.
*
* @param appUUID UUID of the application release.
* @param offsetValue offset value for get paginated request.
* @param limitValue limit value for get paginated request.
* @param status status of the devices.
* @return deviceDetails - device details for given application release.
* @throws {@link ApplicationManagementException} Exception of the application management
*/
PaginationResult getAppInstalledDevices(int offsetValue, int limitValue, String appUUID,
String status) throws ApplicationManagementException;
/***
* This method used to get category details.
*
* @param appUUID UUID of the application release.
* @param subType subscription type of the application.
* @param offsetValue offset value for get paginated request.
* @param limitValue limit value for get paginated request.
* @return {@link PaginationResult} pagination result of the category details.
* @throws {@link ApplicationManagementException} Exception of the application management
*/
PaginationResult getAppInstalledCategories(int offsetValue, int limitValue, String appUUID,
String subType) throws ApplicationManagementException;
} }

@ -83,8 +83,8 @@ public interface SubscriptionDAO {
List<DeviceSubscriptionDTO> getDeviceSubscriptions(int appReleaseId, int tenantId) throws List<DeviceSubscriptionDTO> getDeviceSubscriptions(int appReleaseId, int tenantId) throws
ApplicationManagementDAOException; ApplicationManagementDAOException;
Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int tenantId) throws Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int appReleaseId, int tenantId)
ApplicationManagementDAOException; throws ApplicationManagementDAOException;
List<String> getSubscribedUserNames(List<String> users, int tenantId) throws List<String> getSubscribedUserNames(List<String> users, int tenantId) throws
ApplicationManagementDAOException; ApplicationManagementDAOException;
@ -168,6 +168,46 @@ public interface SubscriptionDAO {
* @return {@link ScheduledSubscriptionDTO} * @return {@link ScheduledSubscriptionDTO}
* @throws ApplicationManagementDAOException if error occurred while retrieving the subscription * @throws ApplicationManagementDAOException if error occurred while retrieving the subscription
*/ */
ScheduledSubscriptionDTO getPendingScheduledSubscriptionByTaskName(String taskName) ScheduledSubscriptionDTO getPendingScheduledSubscriptionByTaskName(String taskName) throws ApplicationManagementDAOException;
/**
* This method is used to get the details of users
*
* @param tenantId id of the current tenant
* @param offsetValue offset value for get paginated result
* @param limitValue limit value for get paginated result
* @param appReleaseId id of the application release.
* @return subscribedUsers - list of app subscribed users.
* @throws {@link ApplicationManagementDAOException} if connections establishment fails.
*/
List<String> getAppSubscribedUsers(int offsetValue, int limitValue, int appReleaseId,
int tenantId)
throws ApplicationManagementDAOException;
/**
* This method is used to get the details of roles
*
* @param tenantId id of the current tenant
* @param offsetValue offset value for get paginated request.
* @param limitValue limit value for get paginated request.
* @param appReleaseId id of the application release.
* @return subscribedRoles - list of app subscribed roles.
* @throws {@link ApplicationManagementDAOException} if connections establishment fails.
*/
List<String> getAppSubscribedRoles(int offsetValue, int limitValue, int appReleaseId,
int tenantId)
throws ApplicationManagementDAOException;
/**
* This method is used to get the details of subscribed groups
*
* @param tenantId id of the current tenant
* @param offsetValue offset value for get paginated request.
* @param limitValue limit value for get paginated request.
* @param appReleaseId id of the application release.
* @return subscribedGroups - list of app subscribed groups.
* @throws {@link ApplicationManagementDAOException} if connections establishment fails.
*/
List<String> getAppSubscribedGroups(int offsetValue, int limitValue, int appReleaseId, int tenantId)
throws ApplicationManagementDAOException; throws ApplicationManagementDAOException;
} }

@ -356,6 +356,7 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
+ "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, " + "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, "
+ "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, " + "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, "
+ "DS.ACTION_TRIGGERED_FROM AS ACTION_TRIGGERED_FROM, " + "DS.ACTION_TRIGGERED_FROM AS ACTION_TRIGGERED_FROM, "
+ "DS.STATUS AS STATUS,"
+ "DS.DM_DEVICE_ID AS DEVICE_ID " + "DS.DM_DEVICE_ID AS DEVICE_ID "
+ "FROM AP_DEVICE_SUBSCRIPTION DS " + "FROM AP_DEVICE_SUBSCRIPTION DS "
+ "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.TENANT_ID=?"; + "WHERE DS.AP_APP_RELEASE_ID = ? AND DS.TENANT_ID=?";
@ -385,7 +386,8 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
} }
@Override @Override
public Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int tenantId) public Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int appReleaseId,
int tenantId)
throws ApplicationManagementDAOException { throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get device subscriptions for given device ids."); log.debug("Request received in DAO Layer to get device subscriptions for given device ids.");
@ -406,13 +408,14 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
+ "DS.DM_DEVICE_ID AS DEVICE_ID, " + "DS.DM_DEVICE_ID AS DEVICE_ID, "
+ "DS.STATUS AS STATUS " + "DS.STATUS AS STATUS "
+ "FROM AP_DEVICE_SUBSCRIPTION DS " + "FROM AP_DEVICE_SUBSCRIPTION DS "
+ "WHERE DS.DM_DEVICE_ID IN (", ") AND TENANT_ID = ?"); + "WHERE DS.DM_DEVICE_ID IN (", ") AND AP_APP_RELEASE_ID = ? AND TENANT_ID = ?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add); deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString(); String query = joiner.toString();
try (PreparedStatement ps = conn.prepareStatement(query)) { try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) { for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId); ps.setObject(index++, deviceId);
} }
ps.setInt(index++, appReleaseId);
ps.setInt(index, tenantId); ps.setInt(index, tenantId);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
@ -575,8 +578,8 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
for (Integer deviceId : deviceIds) { for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId); ps.setObject(index++, deviceId);
} }
ps.setInt(index++, tenantId); ps.setInt(index++, applicationReleaseId);
ps.setInt(index, applicationReleaseId); ps.setInt(index, tenantId);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
subscribedDevices.add(rs.getInt("DM_DEVICE_ID")); subscribedDevices.add(rs.getInt("DM_DEVICE_ID"));
@ -847,6 +850,45 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
} }
} }
public List<String> getAppSubscribedUsers(int offsetValue, int limitValue, int appReleaseId,
int tenantId)
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get already subscribed users for " +
"given app release id.");
}
try {
Connection conn = this.getDBConnection();
List<String> subscribedUsers = new ArrayList<>();
String sql = "SELECT "
+ "US.USER_NAME AS USER "
+ "FROM AP_USER_SUBSCRIPTION US "
+ "WHERE "
+ "AP_APP_RELEASE_ID = ? AND TENANT_ID = ? LIMIT ?,?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, appReleaseId);
stmt.setInt(2, tenantId);
stmt.setInt(3, offsetValue);
stmt.setInt(4, limitValue);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
subscribedUsers.add(rs.getString("USER"));
}
}
return subscribedUsers;
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to get already " +
"subscribed users for given app release id.";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while getting subscribed users for given app release id.";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override @Override
public List<ScheduledSubscriptionDTO> getScheduledSubscriptionByStatus(ExecutionStatus status, boolean deleted) public List<ScheduledSubscriptionDTO> getScheduledSubscriptionByStatus(ExecutionStatus status, boolean deleted)
throws ApplicationManagementDAOException { throws ApplicationManagementDAOException {
@ -916,6 +958,45 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
} }
} }
public List<String> getAppSubscribedRoles(int offsetValue, int limitValue, int appReleaseId,
int tenantId)
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get already subscribed roles for " +
"given app release id.");
}
try {
Connection conn = this.getDBConnection();
List<String> subscribedRoles = new ArrayList<>();
String sql = "SELECT "
+ "US.ROLE_NAME AS ROLE "
+ "FROM AP_ROLE_SUBSCRIPTION US "
+ "WHERE "
+ "AP_APP_RELEASE_ID = ? AND TENANT_ID = ? LIMIT ?,?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, appReleaseId);
ps.setInt(2, tenantId);
ps.setInt(3, offsetValue);
ps.setInt(4, limitValue);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
subscribedRoles.add(rs.getString("ROLE"));
}
}
return subscribedRoles;
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to get already " +
"subscribed roles for given app release id.";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while getting subscribed roles for given app release id.";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override @Override
public ScheduledSubscriptionDTO getPendingScheduledSubscriptionByTaskName(String taskName) public ScheduledSubscriptionDTO getPendingScheduledSubscriptionByTaskName(String taskName)
throws ApplicationManagementDAOException { throws ApplicationManagementDAOException {
@ -955,4 +1036,45 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
throw new ApplicationManagementDAOException(msg, e); throw new ApplicationManagementDAOException(msg, e);
} }
} }
@Override
public List<String> getAppSubscribedGroups(int offsetValue, int limitValue, int appReleaseId,
int tenantId)
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get already subscribed groups for " +
"given app release id.");
}
try {
Connection conn = this.getDBConnection();
List<String> subscribedGroups = new ArrayList<>();
String sql = "SELECT "
+ "GS.GROUP_NAME AS GROUPS "
+ "FROM AP_GROUP_SUBSCRIPTION GS "
+ "WHERE "
+ "AP_APP_RELEASE_ID = ? AND TENANT_ID = ? LIMIT ?,?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, appReleaseId);
ps.setInt(2, tenantId);
ps.setInt(3, offsetValue);
ps.setInt(4, limitValue);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
subscribedGroups.add(rs.getString("GROUPS"));
}
}
return subscribedGroups;
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to get already " +
"subscribed groups for given app release id.";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "SQL Error occurred while getting subscribed groups for given " +
"app release id.";
log.error(msg, e);
throw new ApplicationManagementDAOException(msg, e);
}
}
} }

@ -18,9 +18,6 @@
package org.wso2.carbon.device.application.mgt.core.impl; package org.wso2.carbon.device.application.mgt.core.impl;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PostMethod;
@ -77,7 +74,6 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
@ -86,6 +82,7 @@ import org.wso2.carbon.device.mgt.core.util.MDMAndroidOperationUtil;
import org.wso2.carbon.device.mgt.core.util.MDMIOSOperationUtil; import org.wso2.carbon.device.mgt.core.util.MDMIOSOperationUtil;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.io.IOException; import java.io.IOException;
@ -346,35 +343,45 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} }
/***
* This method perform given action (i.e APP INSTALL or APP UNINSTALL) on given set of devices.
*
* @param deviceType Application supported device type.
* @param devices List of devices that action is triggered.
* @param applicationDTO Application data
* @param subType Subscription type (i.e USER, ROLE, GROUP or DEVICE)
* @param subscribers Subscribers
* @param action Performing action. (i.e INSTALL or UNINSTALL)
* @return {@link ApplicationInstallResponse}
* @throws ApplicationManagementException if error occured when adding operation on device or updating subscription
* data.
*/
private ApplicationInstallResponse performActionOnDevices(String deviceType, List<Device> devices, private ApplicationInstallResponse performActionOnDevices(String deviceType, List<Device> devices,
ApplicationDTO applicationDTO, String subType, List<String> subscribers, String action) ApplicationDTO applicationDTO, String subType, List<String> subscribers, String action)
throws ApplicationManagementException { throws ApplicationManagementException {
SubscribingDeviceIdHolder subscribingDeviceIdHolder = getSubscribingDeviceIdHolder(devices); SubscribingDeviceIdHolder subscribingDeviceIdHolder = getSubscribingDeviceIdHolder(devices,
applicationDTO.getApplicationReleaseDTOs().get(0).getId());
List<Activity> activityList = new ArrayList<>(); List<Activity> activityList = new ArrayList<>();
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>(); List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
List<DeviceIdentifier> ignoredDeviceIdentifiers = new ArrayList<>(); List<DeviceIdentifier> ignoredDeviceIdentifiers = new ArrayList<>();
Map<String, List<DeviceIdentifier>> deviceIdentifierMap = new HashMap<>(); Map<String, List<DeviceIdentifier>> deviceIdentifierMap = new HashMap<>();
if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) { if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) {
deviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getSubscribableDevices().keySet()); deviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getAppInstallableDevices().keySet());
ignoredDeviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getSubscribedDevices().keySet()); ignoredDeviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getAppInstalledDevices().keySet());
if (deviceIdentifiers.isEmpty()) {
ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse();
applicationInstallResponse.setIgnoredDeviceIdentifiers(ignoredDeviceIdentifiers);
return applicationInstallResponse;
}
} else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action)) { } else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action)) {
deviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getSubscribedDevices().keySet()); deviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getAppInstalledDevices().keySet());
ignoredDeviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getSubscribableDevices().keySet()); ignoredDeviceIdentifiers = new ArrayList<>(subscribingDeviceIdHolder.getAppInstallableDevices().keySet());
if (deviceIdentifiers.isEmpty()) { }
ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse();
applicationInstallResponse.setIgnoredDeviceIdentifiers(ignoredDeviceIdentifiers); if (deviceIdentifiers.isEmpty()) {
return applicationInstallResponse; ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse();
} applicationInstallResponse.setIgnoredDeviceIdentifiers(ignoredDeviceIdentifiers);
return applicationInstallResponse;
} }
//device type is getting null when we try to perform action on Web Clip.
if (deviceType == null) { if (deviceType == null) {
for (DeviceIdentifier identifier : deviceIdentifiers) { for (DeviceIdentifier identifier : deviceIdentifiers) {
List<DeviceIdentifier> identifiers; List<DeviceIdentifier> identifiers;
@ -417,28 +424,37 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return applicationInstallResponse; return applicationInstallResponse;
} }
private SubscribingDeviceIdHolder getSubscribingDeviceIdHolder(List<Device> devices) /***
* Filter given devices and davide given list of device into two sets, those are already application installed
* devices and application installable devices.
*
* @param devices List of {@link Device}
* @param appReleaseId Application release id.
* @return {@link SubscribingDeviceIdHolder}
* @throws ApplicationManagementException if error occured while getting device subscriptions for applicaion.
*/
private SubscribingDeviceIdHolder getSubscribingDeviceIdHolder(List<Device> devices, int appReleaseId)
throws ApplicationManagementException { throws ApplicationManagementException {
Map<DeviceIdentifier, Integer> subscribedDevices = new HashMap<>(); Map<DeviceIdentifier, Integer> appInstalledDevices = new HashMap<>();
Map<DeviceIdentifier, Integer> subscribableDevices = new HashMap<>(); Map<DeviceIdentifier, Integer> appInstallableDevices = new HashMap<>();
List<Integer> filteredDeviceIds = devices.stream().map(Device::getId).collect(Collectors.toList()); List<Integer> deviceIds = devices.stream().map(Device::getId).collect(Collectors.toList());
//get device subscriptions for given device id list. //get device subscriptions for given device id list.
Map<Integer, DeviceSubscriptionDTO> deviceSubscriptions = getDeviceSubscriptions(filteredDeviceIds); Map<Integer, DeviceSubscriptionDTO> deviceSubscriptions = getDeviceSubscriptions(deviceIds, appReleaseId);
for (Device device : devices) { for (Device device : devices) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType()); DeviceIdentifier deviceIdentifier = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType());
DeviceSubscriptionDTO deviceSubscriptionDTO = deviceSubscriptions.get(device.getId()); DeviceSubscriptionDTO deviceSubscriptionDTO = deviceSubscriptions.get(device.getId());
if (deviceSubscriptionDTO != null && !deviceSubscriptionDTO.isUnsubscribed() && Operation.Status.COMPLETED if (deviceSubscriptionDTO != null && !deviceSubscriptionDTO.isUnsubscribed() && Operation.Status.COMPLETED
.toString().equals(deviceSubscriptionDTO.getStatus())) { .toString().equals(deviceSubscriptionDTO.getStatus())) {
subscribedDevices.put(deviceIdentifier, device.getId()); appInstalledDevices.put(deviceIdentifier, device.getId());
} else { } else {
subscribableDevices.put(deviceIdentifier, device.getId()); appInstallableDevices.put(deviceIdentifier, device.getId());
} }
} }
SubscribingDeviceIdHolder subscribingDeviceIdHolder = new SubscribingDeviceIdHolder(); SubscribingDeviceIdHolder subscribingDeviceIdHolder = new SubscribingDeviceIdHolder();
subscribingDeviceIdHolder.setSubscribableDevices(subscribableDevices); subscribingDeviceIdHolder.setAppInstallableDevices(appInstallableDevices);
subscribingDeviceIdHolder.setSubscribedDevices(subscribedDevices); subscribingDeviceIdHolder.setAppInstalledDevices(appInstalledDevices);
return subscribingDeviceIdHolder; return subscribingDeviceIdHolder;
} }
@ -458,6 +474,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} }
/***
* Get Application with application release which has given UUID.
*
* @param uuid UUID of the application release.
* @return {@link ApplicationDTO}
* @throws ApplicationManagementException if error occurred while getting application data from database or
* verifying whether application is in installable state.
*/
private ApplicationDTO getApplicationDTO(String uuid) throws ApplicationManagementException { private ApplicationDTO getApplicationDTO(String uuid) throws ApplicationManagementException {
ApplicationDTO applicationDTO; ApplicationDTO applicationDTO;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
@ -531,7 +555,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
for (Activity activity : activities) { for (Activity activity : activities) {
int operationId = Integer.parseInt(activity.getActivityId().split("ACTIVITY_")[1]); int operationId = Integer.parseInt(activity.getActivityId().split("ACTIVITY_")[1]);
List<Integer> operationAddedDeviceIds = getOperationAddedDeviceIds(activity, List<Integer> operationAddedDeviceIds = getOperationAddedDeviceIds(activity,
subscribingDeviceIdHolder.getSubscribableDevices()); subscribingDeviceIdHolder.getAppInstallableDevices());
List<Integer> alreadySubscribedDevices = subscriptionDAO List<Integer> alreadySubscribedDevices = subscriptionDAO
.getSubscribedDeviceIds(operationAddedDeviceIds, applicationReleaseId, tenantId); .getSubscribedDeviceIds(operationAddedDeviceIds, applicationReleaseId, tenantId);
if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) { if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) {
@ -548,7 +572,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
deviceSubIds.addAll(subscribingDevices); deviceSubIds.addAll(subscribingDevices);
} else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action) && !alreadySubscribedDevices.isEmpty()) { } else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action) && !alreadySubscribedDevices.isEmpty()) {
List<Integer> deviceResubscribingIds = subscriptionDAO List<Integer> deviceResubscribingIds = subscriptionDAO
.updateDeviceSubscription(username, alreadySubscribedDevices, false, subType, .updateDeviceSubscription(username, alreadySubscribedDevices, true, subType,
Operation.Status.PENDING.toString(), applicationReleaseId, tenantId); Operation.Status.PENDING.toString(), applicationReleaseId, tenantId);
deviceSubIds.addAll(deviceResubscribingIds); deviceSubIds.addAll(deviceResubscribingIds);
} }
@ -586,13 +610,13 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return deviceIds; return deviceIds;
} }
private Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> filteredDeviceIds) private Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int appReleaseId)
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try { try {
ConnectionManagerUtil.openDBConnection(); ConnectionManagerUtil.openDBConnection();
return this.subscriptionDAO.getDeviceSubscriptions(filteredDeviceIds, tenantId); return this.subscriptionDAO.getDeviceSubscriptions(deviceIds, appReleaseId, tenantId);
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
String msg = "Error occured when getting device subscriptions for given device IDs"; String msg = "Error occured when getting device subscriptions for given device IDs";
log.error(msg, e); log.error(msg, e);
@ -661,6 +685,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
app.setLocation(application.getApplicationReleases().get(0).getInstallerPath()); app.setLocation(application.getApplicationReleases().get(0).getInstallerPath());
return MDMAndroidOperationUtil.createInstallAppOperation(app); return MDMAndroidOperationUtil.createInstallAppOperation(app);
} else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action)) { } else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action)) {
app.setType(mobileAppType);
return MDMAndroidOperationUtil.createAppUninstallOperation(app); return MDMAndroidOperationUtil.createAppUninstallOperation(app);
} else { } else {
String msg = "Invalid Action is found. Action: " + action; String msg = "Invalid Action is found. Action: " + action;
@ -770,10 +795,117 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (IOException e) { } catch (IOException e) {
String msg = "Error while installing the enrollment with id: " + applicationPolicyDTO.getApplicationDTO() String msg = "Error while installing the enrollment with id: " + applicationPolicyDTO.getApplicationDTO().getId()
.getId() + " on device"; + " on device";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
}
@Override
public PaginationResult getAppInstalledDevices(int offsetValue, int limitValue, String appUUID,
String status)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
DeviceManagementProviderService deviceManagementProviderService = HelperUtil
.getDeviceManagementProviderService();
try {
ConnectionManagerUtil.openDBConnection();
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(appUUID, tenantId);
int applicationReleaseId = applicationDTO.getApplicationReleaseDTOs().get(0).getId();
List<DeviceSubscriptionDTO> deviceSubscriptionDTOS = subscriptionDAO
.getDeviceSubscriptions(applicationReleaseId, tenantId);
if (deviceSubscriptionDTOS.isEmpty()) {
String msg = "Couldn't found an subscribed devices for application release id: "
+ applicationReleaseId;
log.info(msg);
}
List<Integer> deviceIdList = new ArrayList<>();
for (DeviceSubscriptionDTO deviceIds : deviceSubscriptionDTOS) {
deviceIdList.add(deviceIds.getDeviceId());
}
//pass the device id list to device manager service method
try {
PaginationResult deviceDetails = deviceManagementProviderService
.getAppSubscribedDevices(offsetValue ,limitValue, deviceIdList, status);
if (deviceDetails == null) {
String msg = "Couldn't found an subscribed devices details for device ids: "
+ deviceIdList;
log.error(msg);
throw new NotFoundException(msg);
}
return deviceDetails;
} catch (DeviceManagementException e) {
String msg = "service error occurred while getting data from the service";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred when get application release data for application" +
" release UUID: " + appUUID;
log.error(msg, e); log.error(msg, e);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (DBConnectionException e) {
String msg = "DB Connection error occurred while getting device details that " +
"given application id";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
@Override
public PaginationResult getAppInstalledCategories(int offsetValue, int limitValue,
String appUUID, String subType)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
PaginationResult paginationResult = new PaginationResult();
try {
ConnectionManagerUtil.openDBConnection();
ApplicationDTO applicationDTO = this.applicationDAO
.getAppWithRelatedRelease(appUUID, tenantId);
int applicationReleaseId = applicationDTO.getApplicationReleaseDTOs().get(0).getId();
int count = 0;
List<String> SubscriptionList = new ArrayList<>();
if (SubscriptionType.USER.toString().equalsIgnoreCase(subType)) {
SubscriptionList = subscriptionDAO
.getAppSubscribedUsers(offsetValue, limitValue, applicationReleaseId, tenantId);
} else if (SubscriptionType.ROLE.toString().equalsIgnoreCase(subType)) {
SubscriptionList = subscriptionDAO
.getAppSubscribedRoles(offsetValue, limitValue, applicationReleaseId, tenantId);
} else if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) {
SubscriptionList = subscriptionDAO
.getAppSubscribedGroups(offsetValue, limitValue, applicationReleaseId, tenantId);
}
count = SubscriptionList.size();
paginationResult.setData(SubscriptionList);
paginationResult.setRecordsFiltered(count);
paginationResult.setRecordsTotal(count);
return paginationResult;
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred when get application release data for application" +
" release UUID: " + appUUID;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (DBConnectionException e) {
String msg = "DB Connection error occurred while getting category details that " +
"given application id";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
} }
} }
} }

@ -58,7 +58,7 @@
} }
.mobile-menu-button{ .mobile-menu-button{
margin-top: 4%; margin-top: 15px;
} }
Header{ Header{
@ -68,7 +68,7 @@
} }
.dashboard-body{ .dashboard-body{
margin-top: 14%; margin-top: 50px;
} }
.logo-image { .logo-image {
@ -80,7 +80,7 @@
@media screen and (max-height: 350px) { @media screen and (max-height: 350px) {
.mobile-menu-button{ .mobile-menu-button{
margin-top: 2%; margin-top: 15px;
} }
.dashboard-body{ .dashboard-body{
margin-top: 9%; margin-top: 9%;

@ -40,14 +40,14 @@ class Dashboard extends React.Component {
this.Logo = this.config.theme.logo; this.Logo = this.config.theme.logo;
} }
showDrawer = () => { showMobileNavigationBar = () => {
this.setState({ this.setState({
visible: true, visible: true,
collapsed: !this.state.collapsed collapsed: !this.state.collapsed
}); });
}; };
onClose = () => { onCloseMobileNavigationBar = () => {
this.setState({ this.setState({
visible: false, visible: false,
}); });
@ -131,7 +131,7 @@ class Dashboard extends React.Component {
<Layout className="mobile-layout"> <Layout className="mobile-layout">
<div className="mobile-menu-button"> <div className="mobile-menu-button">
<Button type="link" onClick={this.showDrawer}> <Button type="link" onClick={this.showMobileNavigationBar}>
<Icon type={this.state.collapsed ? 'menu-fold' : 'menu-unfold'} className="bar-icon"/> <Icon type={this.state.collapsed ? 'menu-fold' : 'menu-unfold'} className="bar-icon"/>
</Button> </Button>
</div> </div>
@ -146,7 +146,7 @@ class Dashboard extends React.Component {
} }
placement="left" placement="left"
closable={false} closable={false}
onClose={this.onClose} onClose={this.onCloseMobileNavigationBar}
visible={this.state.visible} visible={this.state.visible}
getContainer={false} getContainer={false}
style={{position: 'absolute'}}> style={{position: 'absolute'}}>
@ -214,6 +214,6 @@ class Dashboard extends React.Component {
</div> </div>
); );
} }
} };
export default withConfigContext(Dashboard); export default withConfigContext(Dashboard);

@ -20,6 +20,7 @@ package org.wso2.carbon.device.application.mgt.store.api.services;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses; import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension; import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ExtensionProperty;
@ -27,15 +28,17 @@ import io.swagger.annotations.Info;
import io.swagger.annotations.SwaggerDefinition; import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag; import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.application.mgt.common.ErrorResponse;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import javax.validation.Valid; import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.Consumes;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List; import java.util.List;
@ -181,4 +184,133 @@ public interface SubscriptionManagementAPI {
) )
@QueryParam("timestamp") String timestamp @QueryParam("timestamp") String timestamp
); );
@GET
@Path("/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get device details that have a given application install",
notes = "This will get the device details that have a given application install, if exists",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved device details.",
response = List.class,
responseContainer = "List"),
@ApiResponse(
code = 404,
message = "Not Found. \n No Application found which has application release of UUID.",
response = ErrorResponse.class),
@ApiResponse(
code = 400,
message = "Bad Request. \n Found invalid payload with the request.",
response = List.class),
@ApiResponse(
code = 403,
message = "Forbidden. \n Don't have permission to get the details.",
response = List.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting data",
response = ErrorResponse.class)
})
Response getAppInstalledDevices(
@ApiParam(
name="uuid",
value="uuid of the application release.",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items.",
defaultValue = "0")
@QueryParam("offset") int offset,
@ApiParam(
name = "limit",
value = "Provide how many device details you require from the starting pagination index/offset.",
defaultValue = "5")
@QueryParam("limit") int limit,
@ApiParam(
name = "status",
value = "Provide the device status details, such as active or inactive.")
@QueryParam("status") String status
);
@GET
@Path("/{uuid}/{subType}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get category details that have a given application install",
notes = "This will get the category details that have a given application install, if exists",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved categories details.",
response = List.class,
responseContainer = "List"),
@ApiResponse(
code = 404,
message = "Not Found. \n No Application found which has application " +
"release of UUID.",
response = ErrorResponse.class),
@ApiResponse(
code = 400,
message = "Bad Request. \n Found invalid payload with the request.",
response = List.class),
@ApiResponse(
code = 403,
message = "Forbidden. \n Don't have permission to get the details.",
response = List.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting data",
response = ErrorResponse.class)
})
Response getAppInstalledCategories(
@ApiParam(
name="uuid",
value="uuid of the application release.",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(
name="subType",
value="Subscription type of the application release.",
required = true)
@PathParam("subType") String subType,
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items.",
defaultValue = "0")
@QueryParam("offset") int offset,
@ApiParam(
name = "limit",
value = "Provide how many device details you require from the starting " +
"pagination index/offset.",
defaultValue = "5")
@QueryParam("limit") int limit
);
} }

@ -1,21 +1,3 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* /*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. * Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
* *
@ -46,20 +28,31 @@ import org.wso2.carbon.device.application.mgt.common.SubscriptionType;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationOperationTaskException; import org.wso2.carbon.device.application.mgt.core.exception.ApplicationOperationTaskException;
import org.wso2.carbon.device.application.mgt.common.DeviceList;
import org.wso2.carbon.device.application.mgt.common.BasicUserInfo;
import org.wso2.carbon.device.application.mgt.common.BasicUserInfoList;
import org.wso2.carbon.device.application.mgt.common.RoleList;
import org.wso2.carbon.device.application.mgt.common.DeviceGroupList;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.application.mgt.common.SubsciptionType;
import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException; import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException;
import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException; import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException;
import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException; import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException;
import org.wso2.carbon.device.application.mgt.core.task.ScheduledAppSubscriptionTaskManager; import org.wso2.carbon.device.application.mgt.core.task.ScheduledAppSubscriptionTaskManager;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil; import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.application.mgt.store.api.services.SubscriptionManagementAPI; import org.wso2.carbon.device.application.mgt.store.api.services.SubscriptionManagementAPI;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import javax.validation.Valid; import javax.validation.Valid;
import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.Consumes;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -114,6 +107,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
} }
} }
@Override @Override
@POST @POST
@Path("/{uuid}/{subType}/{action}") @Path("/{uuid}/{subType}/{action}")
@ -185,4 +179,114 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
} }
return Response.status(Response.Status.CREATED).build(); return Response.status(Response.Status.CREATED).build();
} }
@GET
@Consumes("application/json")
@Produces("application/json")
@Path("/{uuid}/devices")
public Response getAppInstalledDevices(@PathParam("uuid") String uuid,
@DefaultValue("0")
@QueryParam("offset") int offset,
@DefaultValue("5")
@QueryParam("limit") int limit,
@QueryParam("status") String status) {
try {
SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager();
PaginationResult subscribedDeviceDetails = subscriptionManager
.getAppInstalledDevices(offset, limit, uuid, status);
DeviceList devices = new DeviceList();
devices.setList((List<Device>) subscribedDeviceDetails.getData());
devices.setCount(subscribedDeviceDetails.getRecordsTotal());
return Response.status(Response.Status.OK).entity(devices).build();
} catch (NotFoundException e) {
String msg = "Application with application release UUID: " + uuid + " is not found";
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (BadRequestException e) {
String msg = "Found invalid payload for getting application which has UUID: " + uuid
+ ". Hence verify the payload";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (ForbiddenException e) {
String msg = "Application release is not in the installable state."
+ "Hence you are not permitted to get the devices details.";
log.error(msg, e);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
} catch (ApplicationManagementException e) {
String msg = "Error occurred while getting application with the application release uuid: "
+ uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
@GET
@Consumes("application/json")
@Produces("application/json")
@Path("/{uuid}/{subType}")
public Response getAppInstalledCategories(@PathParam("uuid") String uuid,
@PathParam("subType") String subType,
@DefaultValue("0")
@QueryParam("offset") int offset,
@DefaultValue("5")
@QueryParam("limit") int limit) {
try {
SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager();
PaginationResult subscribedCategoryDetails = subscriptionManager
.getAppInstalledCategories(offset, limit, uuid, subType);
if (SubsciptionType.USER.toString().equalsIgnoreCase(subType)) {
BasicUserInfoList users = new BasicUserInfoList();
users.setList((List<BasicUserInfo>) subscribedCategoryDetails.getData());
users.setCount(subscribedCategoryDetails.getRecordsTotal());
return Response.status(Response.Status.OK).entity(users).build();
} else if (SubsciptionType.ROLE.toString().equalsIgnoreCase(subType)) {
RoleList roles = new RoleList();
roles.setList(subscribedCategoryDetails.getData());
roles.setCount(subscribedCategoryDetails.getRecordsTotal());
return Response.status(Response.Status.OK).entity(roles).build();
} else if (SubsciptionType.GROUP.toString().equalsIgnoreCase(subType)) {
DeviceGroupList groups = new DeviceGroupList();
groups.setList(subscribedCategoryDetails.getData());
groups.setCount(subscribedCategoryDetails.getRecordsTotal());
return Response.status(Response.Status.OK).entity(groups).build();
} else {
String msg = "Found invalid sub type ";
log.error(msg);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
}
} catch (NotFoundException e) {
String msg = "Application with application release UUID: " + uuid + " is not found";
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (BadRequestException e) {
String msg = "Found invalid payload for getting application which has UUID: " + uuid
+ ". Hence verify the payload";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (ForbiddenException e) {
String msg = "Application release is not in the installable state."
+ "Hence you are not permitted to get the devices details.";
log.error(msg, e);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
} catch (ApplicationManagementException e) {
String msg = "Error occurred while getting application with the application " +
"release uuid: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
} }

@ -25,6 +25,7 @@ import DetailedRating from "./DetailedRating";
import Reviews from "./review/Reviews"; import Reviews from "./review/Reviews";
import axios from "axios"; import axios from "axios";
import AppInstallModal from "./install/AppInstallModal"; import AppInstallModal from "./install/AppInstallModal";
import AppUninstallModal from "./install/AppUninstallModal";
import CurrentUsersReview from "./review/CurrentUsersReview"; import CurrentUsersReview from "./review/CurrentUsersReview";
import {withConfigContext} from "../../../context/ConfigContext"; import {withConfigContext} from "../../../context/ConfigContext";
import {handleApiError} from "../../../js/Utils"; import {handleApiError} from "../../../js/Utils";
@ -36,11 +37,12 @@ class ReleaseView extends React.Component {
super(props); super(props);
this.state = { this.state = {
loading: false, loading: false,
appInstallModalVisible: false appInstallModalVisible: false,
appUninstallModalVisible: false
} }
} }
installApp = (type, payload) => { appOperation = (type, payload, operation) => {
const config = this.props.context; const config = this.props.context;
const release = this.props.app.applicationReleases[0]; const release = this.props.app.applicationReleases[0];
const {uuid} = release; const {uuid} = release;
@ -48,7 +50,7 @@ class ReleaseView extends React.Component {
this.setState({ this.setState({
loading: true, loading: true,
}); });
const url = window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/subscription/" + uuid + "/" + type + "/install"; const url = window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/subscription/" + uuid + "/" + type + "/" + operation;
axios.post( axios.post(
url, url,
payload, payload,
@ -64,7 +66,7 @@ class ReleaseView extends React.Component {
notification["success"]({ notification["success"]({
message: 'Done!', message: 'Done!',
description: description:
'App installed triggered.', 'App '+operation+'ed triggered.',
}); });
} else { } else {
this.setState({ this.setState({
@ -74,24 +76,31 @@ class ReleaseView extends React.Component {
message: "There was a problem", message: "There was a problem",
duration: 0, duration: 0,
description: description:
"Error occurred while installing app", "Error occurred while "+operation+"ing app",
}); });
} }
}).catch((error) => { }).catch((error) => {
handleApiError(error,"Error occurred while installing the app."); handleApiError(error,"Error occurred while "+operation+"ing the app.");
}); });
}; };
showAppInstallModal = () => { showAppInstallModal = () => {
this.setState({ this.setState({
appInstallModalVisible: true appInstallModalVisible: true
}); });
}; };
closeAppInstallModal = () => { closeAppOperationModal = () => {
this.setState({ this.setState({
appInstallModalVisible: false appInstallModalVisible: false,
appUninstallModalVisible: false
});
};
showAppUninstallModal = () => {
this.setState({
appUninstallModalVisible: true
}); });
}; };
@ -112,8 +121,14 @@ class ReleaseView extends React.Component {
uuid={release.uuid} uuid={release.uuid}
visible={this.state.appInstallModalVisible} visible={this.state.appInstallModalVisible}
deviceType = {deviceType} deviceType = {deviceType}
onClose={this.closeAppInstallModal} onClose={this.closeAppOperationModal}
onInstall={this.installApp}/> onInstall={this.appOperation}/>
<AppUninstallModal
uuid={release.uuid}
visible={this.state.appUninstallModalVisible}
deviceType = {deviceType}
onClose={this.closeAppOperationModal}
onUninstall={this.appOperation}/>
<div className="release"> <div className="release">
<Row> <Row>
<Col xl={4} sm={6} xs={8} className="release-icon"> <Col xl={4} sm={6} xs={8} className="release-icon">
@ -138,6 +153,12 @@ class ReleaseView extends React.Component {
htmlType="button" type="primary" icon="download">Install</Button> htmlType="button" type="primary" icon="download">Install</Button>
</Button.Group> </Button.Group>
</div> </div>
<div>
<Button.Group style={{float: "right",marginRight:'3%'}}>
<Button onClick={this.showAppUninstallModal} loading={this.state.loading}
htmlType="button" type="primary" icon="delete">UnInstall</Button>
</Button.Group>
</div>
</Col> </Col>
</Row> </Row>
<Divider/> <Divider/>

@ -0,0 +1,61 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://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.
*/
import React from "react";
import {Modal, Tabs} from "antd";
import DeviceUninstall from "./DeviceUninstall";
import UserUninstall from "./UserUninstall";
import RoleUninstall from "./RoleUninstall";
import GroupUninstall from "./GroupUninstall";
const { TabPane } = Tabs;
class AppUninstallModal extends React.Component{
state={
data:[]
};
render() {
const {deviceType} = this.props;
return (
<div>
<Modal
title="Uninstall App"
visible={this.props.visible}
onCancel={this.props.onClose}
footer={null}
>
<Tabs defaultActiveKey="device">
<TabPane tab="Device" key="device">
<DeviceUninstall deviceType={deviceType} onUninstall={this.props.onUninstall} uuid={this.props.uuid}/>
</TabPane>
<TabPane tab="User" key="user">
<UserUninstall onUninstall={this.props.onUninstall} uuid={this.props.uuid}/>
</TabPane>
<TabPane tab="Role" key="role">
<RoleUninstall onUninstall={this.props.onUninstall} uuid={this.props.uuid}/>
</TabPane>
<TabPane tab="Group" key="group">
<GroupUninstall onUninstall={this.props.onUninstall} uuid={this.props.uuid}/>
</TabPane>
</Tabs>
</Modal>
</div>
);
}
}
export default AppUninstallModal;

@ -196,7 +196,7 @@ class DeviceInstall extends React.Component {
type: device.type type: device.type
}); });
}); });
this.props.onInstall("devices", payload); this.props.onInstall("devices", payload, "install");
}; };
render() { render() {

@ -0,0 +1,232 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://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.
*/
import React from "react";
import axios from "axios";
import {Button,Table, Typography} from "antd";
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../../../context/ConfigContext";
import {handleApiError} from "../../../../js/Utils";
const {Text} = Typography;
const columns = [
{
title: 'Device',
dataIndex: 'name',
fixed: 'left',
width: 100,
},
{
title: 'Modal',
dataIndex: 'deviceInfo',
key: 'modal',
render: deviceInfo => `${deviceInfo.vendor} ${deviceInfo.deviceModel}`
// todo add filtering options
},
{
title: 'Owner',
dataIndex: 'enrolmentInfo',
key: 'owner',
render: enrolmentInfo => enrolmentInfo.owner
// todo add filtering options
},
{
title: 'Last Updated',
dataIndex: 'enrolmentInfo',
key: 'dateOfLastUpdate',
render: (data) => {
return (getTimeAgo(data.dateOfLastUpdate));
}
// todo add filtering options
},
{
title: 'Status',
dataIndex: 'enrolmentInfo',
key: 'status',
render: enrolmentInfo => enrolmentInfo.status
// todo add filtering options
},
{
title: 'Ownership',
dataIndex: 'enrolmentInfo',
key: 'ownership',
render: enrolmentInfo => enrolmentInfo.ownership
// todo add filtering options
},
{
title: 'OS Version',
dataIndex: 'deviceInfo',
key: 'osVersion',
render: deviceInfo => deviceInfo.osVersion
// todo add filtering options
},
{
title: 'IMEI',
dataIndex: 'properties',
key: 'imei',
render: properties => {
let imei = "not-found";
for (let i = 0; i < properties.length; i++) {
if (properties[i].name === "IMEI") {
imei = properties[i].value;
}
}
return imei;
}
// todo add filtering options
},
];
const getTimeAgo = (time) => {
const timeAgo = new TimeAgo('en-US');
return timeAgo.format(time);
};
class DeviceUninstall extends React.Component {
constructor(props) {
super(props);
TimeAgo.addLocale(en);
this.state = {
data: [],
pagination: {},
loading: false,
selectedRows: []
};
}
rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
this.setState({
selectedRows: selectedRows
})
},
getCheckboxProps: record => ({
disabled: record.name === 'Disabled User', // Column configuration not to be checked
name: record.name,
}),
};
componentDidMount() {
this.fetch();
}
//fetch data from api
fetch = (params = {}) => {
const config = this.props.context;
this.setState({loading: true});
const {deviceType} = this.props;
// get current page
const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
const extraParams = {
offset: 10 * (currentPage - 1), //calculate the offset
limit: 10,
status: "ACTIVE",
};
if (deviceType !== 'ANY') {
extraParams.type = deviceType;
}
// note: encode with '%26' not '&'
const encodedExtraParams = Object.keys(extraParams).map(key => key + '=' + extraParams[key]).join('&');
const uuid = this.props.uuid;
axios.get(
window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/subscription/" + uuid + "/"+
"/devices?" + encodedExtraParams,
).then(res => {
if (res.status === 200) {
const pagination = {...this.state.pagination};
this.setState({
loading: false,
data: res.data.data.devices,
pagination,
});
}
}).catch((error) => {
handleApiError(error,"Error occurred while trying to load devices.");
this.setState({loading: false});
});
};
handleTableChange = (pagination, filters, sorter) => {
const pager = {...this.state.pagination};
pager.current = pagination.current;
this.setState({
pagination: pager,
});
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
};
uninstall = () => {
const {selectedRows} = this.state;
const payload = [];
selectedRows.map(device => {
payload.push({
id: device.deviceIdentifier,
type: device.type
});
});
this.props.onUninstall("devices", payload, "uninstall");
};
render() {
const {data, pagination, loading, selectedRows} = this.state;
return (
<div>
<Text>
Start uninstalling the application for devices by selecting the corresponding devices.
Select uninstall to automatically start uninstalling the application for the respective devices.
</Text>
<Table
style={{paddingTop: 20}}
columns={columns}
rowKey={record => record.deviceIdentifier}
dataSource={data}
pagination={{
...pagination,
size: "small",
showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} devices`
}}
loading={loading}
onChange={this.handleTableChange}
rowSelection={this.rowSelection}
scroll={{x: 1000}}
/>
<div style={{paddingTop: 10, textAlign: "right"}}>
<Button disabled={selectedRows.length === 0} htmlType="button" type="primary"
onClick={this.uninstall}>
Uninstall
</Button>
</div>
</div>
);
}
}
export default withConfigContext(DeviceUninstall);

@ -47,7 +47,7 @@ class GroupInstall extends React.Component {
const config = this.props.context; const config = this.props.context;
this.setState({data: [], fetching: true}); this.setState({data: [], fetching: true});
axios.post( axios.get(
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/groups?name=" + value, window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/groups?name=" + value,
).then(res => { ).then(res => {
@ -85,7 +85,7 @@ class GroupInstall extends React.Component {
value.map(val=>{ value.map(val=>{
data.push(val.key); data.push(val.key);
}); });
this.props.onInstall("group",data); this.props.onInstall("group", data, "install");
}; };
render() { render() {

@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://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.
*/
import React from "react";
import {Typography, Select, Spin, message, notification, Button} from "antd";
import debounce from 'lodash.debounce';
import axios from "axios";
import {withConfigContext} from "../../../../context/ConfigContext";
import {handleApiError} from "../../../../js/Utils";
const {Text} = Typography;
const {Option} = Select;
class GroupUninstall extends React.Component {
constructor(props) {
super(props);
this.lastFetchId = 0;
this.fetchUser = debounce(this.fetchUser, 800);
}
state = {
data: [],
value: [],
fetching: false,
};
fetchUser = value => {
this.lastFetchId += 1;
const fetchId = this.lastFetchId;
const config = this.props.context;
this.setState({data: [], fetching: true});
const uuid = this.props.uuid;
axios.get(
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store+ "/subscription/" + uuid + "/"+
"/GROUP?",
).then(res => {
if (res.status === 200) {
if (fetchId !== this.lastFetchId) {
// for fetch callback order
return;
}
const data = res.data.data.deviceGroups.map(group => ({
text: group,
value: group,
}));
this.setState({data, fetching: false});
}
}).catch((error) => {
handleApiError(error,"Error occurred while trying to load groups.");
this.setState({fetching: false});
});
};
handleChange = value => {
this.setState({
value,
data: [],
fetching: false,
});
};
install = () =>{
const {value} = this.state;
const data = [];
value.map(val=>{
data.push(val.key);
});
this.props.onInstall("group", data, "uninstall");
};
render() {
const {fetching, data, value} = this.state;
return (
<div>
<Text>Start uninstalling the application for one or more groups by entering the corresponding group name. Select uninstall to automatically start uninstalling the application for the respective device group/ groups.</Text>
<br/>
<br/>
<Select
mode="multiple"
labelInValue
value={value}
placeholder="Search groups"
notFoundContent={fetching ? <Spin size="small"/> : null}
filterOption={false}
onSearch={this.fetchUser}
onChange={this.handleChange}
style={{width: '100%'}}
>
{data.map(d => (
<Option key={d.value}>{d.text}</Option>
))}
</Select>
<div style={{paddingTop:10, textAlign:"right"}}>
<Button disabled={value.length===0} htmlType="button" type="primary" onClick={this.install}>Install</Button>
</div>
</div>
);
}
}
export default withConfigContext(GroupUninstall);

@ -85,7 +85,7 @@ class RoleInstall extends React.Component {
value.map(val=>{ value.map(val=>{
data.push(val.key); data.push(val.key);
}); });
this.props.onInstall("role",data); this.props.onInstall("role", data, "install");
}; };
render() { render() {

@ -0,0 +1,124 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://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.
*/
import React from "react";
import {Typography, Select, Spin, message, notification, Button} from "antd";
import debounce from 'lodash.debounce';
import axios from "axios";
import {withConfigContext} from "../../../../context/ConfigContext";
import {handleApiError} from "../../../../js/Utils";
const {Text} = Typography;
const {Option} = Select;
class RoleUninstall extends React.Component {
constructor(props) {
super(props);
this.lastFetchId = 0;
this.fetchUser = debounce(this.fetchUser, 800);
}
state = {
data: [],
value: [],
fetching: false,
};
fetchUser = value => {
const config = this.props.context;
this.lastFetchId += 1;
const fetchId = this.lastFetchId;
this.setState({data: [], fetching: true});
const uuid = this.props.uuid;
axios.get(
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store+ "/subscription/" + uuid + "/"+
"/ROLE?",
).then(res => {
if (res.status === 200) {
if (fetchId !== this.lastFetchId) {
// for fetch callback order
return;
}
const data = res.data.data.roles.map(role => ({
text: role,
value: role,
}));
this.setState({data, fetching: false});
}
}).catch((error) => {
handleApiError(error,"Error occurred while trying to load roles.");
this.setState({fetching: false});
});
};
handleChange = value => {
this.setState({
value,
data: [],
fetching: false,
});
};
install = () =>{
const {value} = this.state;
const data = [];
value.map(val=>{
data.push(val.key);
});
this.props.onInstall("role", data, "uninstall");
};
render() {
const {fetching, data, value} = this.state;
return (
<div>
<Text>Start uninstalling the application for one or more roles by entering the corresponding role name. Select uninstall to automatically start uninstalling the application for the respective user role/roles.</Text>
<br/>
<br/>
<Select
mode="multiple"
labelInValue
value={value}
placeholder="Search roles"
notFoundContent={fetching ? <Spin size="small"/> : null}
filterOption={false}
onSearch={this.fetchUser}
onChange={this.handleChange}
style={{width: '100%'}}
>
{data.map(d => (
<Option key={d.value}>{d.text}</Option>
))}
</Select>
<div style={{paddingTop:10, textAlign:"right"}}>
<Button disabled={value.length===0} htmlType="button" type="primary" onClick={this.install}>Install</Button>
</div>
</div>
);
}
}
export default withConfigContext(RoleUninstall);

@ -87,7 +87,7 @@ class UserInstall extends React.Component {
value.map(val => { value.map(val => {
data.push(val.key); data.push(val.key);
}); });
this.props.onInstall("user", data); this.props.onInstall("user", data, "install");
}; };
render() { render() {

@ -0,0 +1,122 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://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.
*/
import React from "react";
import {Typography, Select, Spin, message, notification, Button} from "antd";
import debounce from 'lodash.debounce';
import axios from "axios";
import {withConfigContext} from "../../../../context/ConfigContext";
import {handleApiError} from "../../../../js/Utils";
const {Text} = Typography;
const {Option} = Select;
class UserUninstall extends React.Component {
constructor(props) {
super(props);
this.lastFetchId = 0;
this.fetchUser = debounce(this.fetchUser, 800);
}
state = {
data: [],
value: [],
fetching: false,
};
fetchUser = (value) => {
const config = this.props.context;
this.lastFetchId += 1;
const fetchId = this.lastFetchId;
this.setState({data: [], fetching: true});
const uuid = this.props.uuid;
axios.get(
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store+ "/subscription/" + uuid + "/"+
"/USER?",
).then(res => {
if (res.status === 200) {
if (fetchId !== this.lastFetchId) {
// for fetch callback order
return;
}
const data = res.data.data.users.map(user => ({
text: user,
value: user,
}));
this.setState({data, fetching: false});
}
}).catch((error) => {
handleApiError(error,"Error occurred while trying to load users.");
this.setState({fetching: false});
});
};
handleChange = value => {
this.setState({
value,
data: [],
fetching: false,
});
};
uninstall = () => {
const {value} = this.state;
const data = [];
value.map(val => {
data.push(val.key);
});
this.props.onUninstall("user", data, "uninstall");
};
render() {
const {fetching, data, value} = this.state;
return (
<div>
<Text>Start uninstalling the application for one or more users by entering the corresponding user name. Select uninstall to automatically start uninstalling the application for the respective user/users. </Text>
<p>Select users</p>
<Select
mode="multiple"
labelInValue
value={value}
placeholder="Enter the username"
notFoundContent={fetching ? <Spin size="small"/> : null}
filterOption={false}
onSearch={this.fetchUser}
onChange={this.handleChange}
style={{width: '100%'}}
>
{data.map(d => (
<Option key={d.value}>{d.text}</Option>
))}
</Select>
<div style={{paddingTop: 10, textAlign: "right"}}>
<Button disabled={value.length===0} htmlType="button" type="primary" onClick={this.uninstall}>Uninstall</Button>
</div>
</div>
);
}
}
export default withConfigContext(UserUninstall);

@ -58,7 +58,7 @@
} }
.mobile-menu-button { .mobile-menu-button {
margin-top: 4%; margin-top: 15px;
} }
Header{ Header{
@ -68,7 +68,7 @@
} }
.dashboard-body{ .dashboard-body{
margin-top: 15%; margin-top: 50px;
} }
.logo-image { .logo-image {
@ -80,7 +80,7 @@
@media only screen and (max-height: 350px) { @media only screen and (max-height: 350px) {
.mobile-menu-button{ .mobile-menu-button{
margin-top: 2%; margin-top: 15px;
} }
.dashboard-body{ .dashboard-body{

@ -36,7 +36,9 @@ class Dashboard extends React.Component {
this.state = { this.state = {
routes: props.routes, routes: props.routes,
selectedKeys: [], selectedKeys: [],
deviceTypes: [] deviceTypes: [],
visible: false,
collapsed: false
}; };
this.logo = this.props.context.theme.logo; this.logo = this.props.context.theme.logo;
} }
@ -72,20 +74,14 @@ class Dashboard extends React.Component {
}) })
}; };
//functions for show the drawer showMobileNavigationBar = () => {
state = {
visible: false,
collapsed: false
};
showDrawer = () => {
this.setState({ this.setState({
visible: true, visible: true,
collapsed: !this.state.collapsed, collapsed: !this.state.collapsed,
}); });
}; };
onClose = () => { onCloseMobileNavigationBar = () => {
this.setState({ this.setState({
visible: false, visible: false,
}); });
@ -153,7 +149,7 @@ class Dashboard extends React.Component {
<Layout className="mobile-layout"> <Layout className="mobile-layout">
<div className="mobile-menu-button"> <div className="mobile-menu-button">
<Button type="link" onClick={this.showDrawer}> <Button type="link" onClick={this.showMobileNavigationBar}>
<Icon type={this.state.collapsed ? 'menu-fold' : 'menu-unfold'} className="bar-icon"/> <Icon type={this.state.collapsed ? 'menu-fold' : 'menu-unfold'} className="bar-icon"/>
</Button> </Button>
</div> </div>
@ -163,7 +159,7 @@ class Dashboard extends React.Component {
</Link>} </Link>}
placement="left" placement="left"
closable={false} closable={false}
onClose={this.onClose} onClose={this.onCloseMobileNavigationBar}
visible={this.state.visible} visible={this.state.visible}
getContainer={false} getContainer={false}
style={{position: 'absolute'}} style={{position: 'absolute'}}

@ -58,6 +58,10 @@
<param-name>isSharedWithAllTenants</param-name> <param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value> <param-value>true</param-value>
</context-param> </context-param>
<context-param>
<param-name>basicAuth</param-name>
<param-value>true</param-value>
</context-param>
<security-constraint> <security-constraint>
<web-resource-collection> <web-resource-collection>

@ -29,8 +29,8 @@
<artifactId>io.entgra.device.mgt.ui</artifactId> <artifactId>io.entgra.device.mgt.ui</artifactId>
<version>3.2.9-SNAPSHOT</version> <version>3.2.9-SNAPSHOT</version>
<packaging>war</packaging> <packaging>war</packaging>
<name>WSO2 Carbon - Device Management UI Component</name> <name>Entgra - Device Management UI Component</name>
<url>http://wso2.org</url> <url>https://entgra.io</url>
<description>This Component contains Device Management UI</description> <description>This Component contains Device Management UI</description>
<dependencies> <dependencies>
</dependencies> </dependencies>

@ -23,6 +23,7 @@ import io.swagger.annotations.ApiModelProperty;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.policy.mgt.DeviceGroupWrapper; import org.wso2.carbon.device.mgt.common.policy.mgt.DeviceGroupWrapper;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import java.util.List; import java.util.List;
@ -102,6 +103,19 @@ public class PolicyWrapper {
required = true) required = true)
private List<DeviceGroupWrapper> deviceGroups; private List<DeviceGroupWrapper> deviceGroups;
@ApiModelProperty(name = "policyType", value = "Type of the corresponding policy",
required = true)
@NotNull
private String policyType;
public String getPolicyType() {
return policyType;
}
public void setPolicyType(String policyType) {
this.policyType = policyType;
}
public Profile getProfile() { public Profile getProfile() {
return profile; return profile;
} }

@ -469,17 +469,21 @@ public interface DeviceManagementService {
String id, String id,
@ApiParam( @ApiParam(
name = "owner", name = "owner",
value = "The owner of the device you want ot get details.", value = "The owner of the device you want ot get details.")
required = false)
@QueryParam("owner") @QueryParam("owner")
@Size(max = 100) @Size(max = 100)
String owner, String owner,
@ApiParam(
name = "ownership",
value = "Device ownership.")
@QueryParam("ownership")
@Size(max = 100)
String ownership,
@ApiParam( @ApiParam(
name = "If-Modified-Since", name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time. \n" + value = "Checks if the requested variant was modified, since the specified date-time. \n" +
"Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z. \n" + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z. \n" +
"Example: Mon, 05 Jan 2014 15:10:00 +0200", "Example: Mon, 05 Jan 2014 15:10:00 +0200")
required = false)
@HeaderParam("If-Modified-Since") @HeaderParam("If-Modified-Since")
String ifModifiedSince); String ifModifiedSince);
@ -1412,21 +1416,18 @@ public interface DeviceManagementService {
name = "If-Modified-Since", name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time. \n" + value = "Checks if the requested variant was modified, since the specified date-time. \n" +
"Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" +
"Example: Mon, 05 Jan 2014 15:10:00 +0200", "Example: Mon, 05 Jan 2014 15:10:00 +0200")
required = false)
@HeaderParam("If-Modified-Since") @HeaderParam("If-Modified-Since")
String ifModifiedSince, String ifModifiedSince,
@ApiParam( @ApiParam(
name = "offset", name = "offset",
value = "The starting pagination index for the complete list of qualified items.", value = "The starting pagination index for the complete list of qualified items.",
required = false,
defaultValue = "0") defaultValue = "0")
@QueryParam("offset") @QueryParam("offset")
int offset, int offset,
@ApiParam( @ApiParam(
name = "limit", name = "limit",
value = "Provide how many activity details you require from the starting pagination index/offset.", value = "Provide how many activity details you require from the starting pagination index/offset.",
required = false,
defaultValue = "5") defaultValue = "5")
@QueryParam("limit") @QueryParam("limit")
int limit, int limit,
@ -1436,7 +1437,12 @@ public interface DeviceManagementService {
required = true, required = true,
defaultValue = "") defaultValue = "")
@QueryParam("owner") @QueryParam("owner")
String owner); String owner,
@ApiParam(
name = "ownership",
value = "Provides the ownership of the required device.")
@QueryParam("owner")
String ownership);
@GET @GET
@Path("/{type}/{id}/effective-policy") @Path("/{type}/{id}/effective-policy")

@ -697,4 +697,87 @@ public interface PolicyManagementService {
@PathParam("deviceId") @PathParam("deviceId")
@Size(max = 45) @Size(max = 45)
String deviceId); String deviceId);
@GET
@Path("/type/{policyType}")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting Details of Policies",
responseContainer = "List",
notes = "Retrieve the details of all the policies filtered by policy type in WSO2 EMM.",
response = Policy.class,
tags = "Device Policy Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:policies:get-details")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched policies.",
response = Policy.class,
responseContainer = "List",
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. \n 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 = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = ("Internal Server Error. \n Server error occurred while fetching the policies."),
response = ErrorResponse.class)
})
Response getPolicies(@ApiParam(
name = "policyType",
value = "The policy type, such as general policy, Geo policy.",
required = true)
@PathParam("policyType")
String policyType,
@ApiParam(
name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time. \n" +
"Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" +
"Example: Mon, 05 Jan 2014 15:10:00 +0200",
required = false)
@HeaderParam("If-Modified-Since")
String ifModifiedSince,
@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 policy details you require from the starting pagination index/offset.",
required = false,
defaultValue = "5")
@QueryParam("limit")
int limit
);
} }

@ -36,6 +36,7 @@
package org.wso2.carbon.device.mgt.jaxrs.service.impl; package org.wso2.carbon.device.mgt.jaxrs.service.impl;
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;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -51,6 +52,7 @@ import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException; 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.authorization.DeviceAccessAuthorizationService;
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.DeviceLocationHistory;
@ -106,6 +108,7 @@ import javax.ws.rs.core.Response;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -383,8 +386,10 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@PathParam("type") @Size(max = 45) String type, @PathParam("type") @Size(max = 45) String type,
@PathParam("id") @Size(max = 45) String id, @PathParam("id") @Size(max = 45) String id,
@QueryParam("owner") @Size(max = 100) String owner, @QueryParam("owner") @Size(max = 100) String owner,
@QueryParam("ownership") @Size(max = 100) String ownership,
@HeaderParam("If-Modified-Since") String ifModifiedSince) { @HeaderParam("If-Modified-Since") String ifModifiedSince) {
Device device = null; Device device;
Date sinceDate = null;
try { try {
RequestValidationUtil.validateDeviceIdentifier(type, id); RequestValidationUtil.validateDeviceIdentifier(type, id);
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
@ -399,61 +404,32 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" + id + "'"; String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" + id + "'";
log.error(msg); log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity( return Response.status(Response.Status.UNAUTHORIZED).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(401l).setMessage(msg).build()).build(); new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_UNAUTHORIZED).setMessage(msg).build()).build();
} }
Date sinceDate = null; DeviceData deviceData = new DeviceData();
if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { deviceData.setDeviceIdentifier(deviceIdentifier);
if (!StringUtils.isBlank(ifModifiedSince)){
SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
try { try {
sinceDate = format.parse(ifModifiedSince); sinceDate = format.parse(ifModifiedSince);
deviceData.setLastModifiedDate(sinceDate);
} catch (ParseException e) { } catch (ParseException e) {
String msg = "Invalid date string is provided in 'If-Modified-Since' header";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity( return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage("Invalid date " + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
"string is provided in 'If-Modified-Since' header").build()).build();
} }
} }
if (!StringUtils.isEmpty(owner)) { if (!StringUtils.isBlank(owner)){
if (authorizedUser.equalsIgnoreCase(owner) || deviceAccessAuthorizationService.isDeviceAdminUser()) { deviceData.setDeviceOwner(owner);
if (sinceDate != null) {
device = dms.getDevice(new DeviceIdentifier(id, type), owner, sinceDate, true);
if (device == null) {
return Response.status(Response.Status.NOT_MODIFIED).entity("No device is modified " +
"after the timestamp provided in 'If-Modified-Since' header").build();
}
} else {
device = dms.getDevice(new DeviceIdentifier(id, type), owner, true);
}
} else {
String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" + id +
"' which belongs to user '" + owner + "'";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(401l).setMessage(msg).build()).build();
}
} else if (deviceAccessAuthorizationService.isDeviceAdminUser()) {
if (sinceDate != null) {
device = dms.getDevice(new DeviceIdentifier(id, type), sinceDate);
if (device == null) {
return Response.status(Response.Status.NOT_MODIFIED).entity("No device is modified " +
"after the timestamp provided in 'If-Modified-Since' header").build();
}
} else {
device = dms.getDevice(new DeviceIdentifier(id, type));
}
} else {
owner = authorizedUser;
if (sinceDate != null) {
device = dms.getDevice(new DeviceIdentifier(id, type), owner, sinceDate, true);
if (device == null) {
return Response.status(Response.Status.NOT_MODIFIED).entity("No device is modified " +
"after the timestamp provided in 'If-Modified-Since' header").build();
}
} else {
device = dms.getDevice(new DeviceIdentifier(id, type), owner, true);
}
} }
if (!StringUtils.isBlank(ownership)){
deviceData.setDeviceOwnership(ownership);
}
device = dms.getDevice(deviceData, true);
} 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);
@ -466,8 +442,12 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} }
if (device == null) { if (device == null) {
if (sinceDate != null) {
return Response.status(Response.Status.NOT_MODIFIED).entity("No device is modified " +
"after the timestamp provided in 'If-Modified-Since' header").build();
}
return Response.status(Response.Status.NOT_FOUND).entity( return Response.status(Response.Status.NOT_FOUND).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(404l).setMessage("Requested device of type '" + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_NOT_FOUND).setMessage("Requested device of type '" +
type + "', which carries id '" + id + "' does not exist").build()).build(); type + "', which carries id '" + id + "' does not exist").build()).build();
} }
return Response.status(Response.Status.OK).entity(device).build(); return Response.status(Response.Status.OK).entity(device).build();
@ -782,7 +762,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@HeaderParam("If-Modified-Since") String ifModifiedSince, @HeaderParam("If-Modified-Since") String ifModifiedSince,
@QueryParam("offset") int offset, @QueryParam("offset") int offset,
@QueryParam("limit") int limit, @QueryParam("limit") int limit,
@QueryParam("owner") String owner) { @QueryParam("owner") String owner,
@QueryParam("ownership") String ownership) {
OperationList operationsList = new OperationList(); OperationList operationsList = new OperationList();
RequestValidationUtil.validateOwnerParameter(owner); RequestValidationUtil.validateOwnerParameter(owner);
RequestValidationUtil.validatePaginationParameters(offset, limit); RequestValidationUtil.validatePaginationParameters(offset, limit);
@ -793,6 +774,9 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
try { try {
RequestValidationUtil.validateDeviceIdentifier(type, id); RequestValidationUtil.validateDeviceIdentifier(type, id);
dms = DeviceMgtAPIUtils.getDeviceManagementService(); dms = DeviceMgtAPIUtils.getDeviceManagementService();
if (!StringUtils.isBlank(ownership)) {
request.setOwnership(ownership);
}
result = dms.getOperations(new DeviceIdentifier(id, type), request); result = dms.getOperations(new DeviceIdentifier(id, type), request);
operationsList.setList((List<? extends Operation>) result.getData()); operationsList.setList((List<? extends Operation>) result.getData());
operationsList.setCount(result.getRecordsTotal()); operationsList.setCount(result.getRecordsTotal());

@ -123,6 +123,7 @@ public class PolicyManagementServiceImpl implements PolicyManagementService {
policy.setUsers(policyWrapper.getUsers()); policy.setUsers(policyWrapper.getUsers());
policy.setCompliance(policyWrapper.getCompliance()); policy.setCompliance(policyWrapper.getCompliance());
policy.setDeviceGroups(policyWrapper.getDeviceGroups()); policy.setDeviceGroups(policyWrapper.getDeviceGroups());
policy.setPolicyType(policyWrapper.getPolicyType());
//TODO iterates the device identifiers to create the object. need to implement a proper DAO layer here. //TODO iterates the device identifiers to create the object. need to implement a proper DAO layer here.
List<Device> devices = new ArrayList<Device>(); List<Device> devices = new ArrayList<Device>();
List<DeviceIdentifier> deviceIdentifiers = policyWrapper.getDeviceIdentifiers(); List<DeviceIdentifier> deviceIdentifiers = policyWrapper.getDeviceIdentifiers();
@ -398,4 +399,33 @@ public class PolicyManagementServiceImpl implements PolicyManagementService {
return Response.status(Response.Status.OK).entity(policy).build(); return Response.status(Response.Status.OK).entity(policy).build();
} }
@GET
@Path("/type/{policyType}")
@Override
public Response getPolicies(
@PathParam("policyType") String policyType,
@HeaderParam("If-Modified-Since") String ifModifiedSince,
@QueryParam("offset") int offset,
@QueryParam("limit") int limit) {
RequestValidationUtil.validatePaginationParameters(offset, limit);
PolicyManagerService policyManagementService = DeviceMgtAPIUtils.getPolicyManagementService();
List<Policy> policies;
List<Policy> filteredPolicies;
PolicyList targetPolicies = new PolicyList();
try {
PolicyAdministratorPoint policyAdministratorPoint = policyManagementService.getPAP();
policies = policyAdministratorPoint.getPolicies(policyType);
targetPolicies.setCount(policies.size());
filteredPolicies = FilteringUtil.getFilteredList(policies, offset, limit);
targetPolicies.setList(filteredPolicies);
} catch (PolicyManagementException e) {
String msg = "Error occurred while retrieving all available policies";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
return Response.status(Response.Status.OK).entity(targetPolicies).build();
}
} }

@ -625,7 +625,8 @@ public class DeviceManagementServiceImplTest {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService); .toReturn(this.deviceManagementProviderService);
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDeviceOperations(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), "", 10, 5, DEFAULT_USERNAME); .getDeviceOperations(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), "", 10, 5, DEFAULT_USERNAME,
DEFAULT_OWNERSHIP);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(),
"Expects to return HTTP 200 when the operation is retrieved successfully."); "Expects to return HTTP 200 when the operation is retrieved successfully.");
} }
@ -637,7 +638,8 @@ public class DeviceManagementServiceImplTest {
Mockito.when(this.deviceManagementProviderService.getOperations(Mockito.any(DeviceIdentifier.class), Mockito.when(this.deviceManagementProviderService.getOperations(Mockito.any(DeviceIdentifier.class),
Mockito.any(PaginationRequest.class))).thenThrow(new OperationManagementException()); Mockito.any(PaginationRequest.class))).thenThrow(new OperationManagementException());
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDeviceOperations(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), "", 10, 5, DEFAULT_USERNAME); .getDeviceOperations(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), "", 10, 5, DEFAULT_USERNAME,
DEFAULT_OWNERSHIP);
Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
"Expects to return HTTP 500 when an exception occurred while retrieving operation list of the device"); "Expects to return HTTP 500 when an exception occurred while retrieving operation list of the device");
} }

@ -0,0 +1,77 @@
/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.common.device.details;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import java.util.Date;
public class DeviceData {
/***
* Identifier of the device, which contains identifier and device ype.
*/
private DeviceIdentifier deviceIdentifier;
/***
* User who is enrolled the device.
*/
private String deviceOwner;
/***
* Last modified date.
*/
private Date lastModifiedDate;
/***
* Current status of the device, e.g ACTIVE, INACTIVE, REMOVED etc.
*/
private String deviceOwnership;
public DeviceIdentifier getDeviceIdentifier() {
return deviceIdentifier;
}
public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) {
this.deviceIdentifier = deviceIdentifier;
}
public String getDeviceOwner() {
return deviceOwner;
}
public void setDeviceOwner(String deviceOwner) {
this.deviceOwner = deviceOwner;
}
public Date getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
public String getDeviceOwnership() {
return deviceOwnership;
}
public void setDeviceOwnership(String deviceOwnership) {
this.deviceOwnership = deviceOwnership;
}
}

@ -177,6 +177,12 @@ public class Policy implements Comparable<Policy>, Serializable {
example = "[]") example = "[]")
private List<DeviceGroupWrapper> deviceGroups; private List<DeviceGroupWrapper> deviceGroups;
@ApiModelProperty(
name = "policyType",
value = "Type of the corresponding policy",
required = true,
example = "GENERAL")
private String policyType;
@XmlElement @XmlElement
public int getId() { public int getId() {
@ -341,6 +347,14 @@ public class Policy implements Comparable<Policy>, Serializable {
this.deviceGroups = deviceGroups; this.deviceGroups = deviceGroups;
} }
public String getPolicyType() {
return policyType;
}
public void setPolicyType(String policyType) {
this.policyType = policyType;
}
@Override @Override
public int compareTo(Policy o) { public int compareTo(Policy o) {
if (this.priorityId == o.priorityId) if (this.priorityId == o.priorityId)

@ -42,6 +42,7 @@ import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceData;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.GeoCluster;
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
@ -139,6 +140,9 @@ public interface DeviceDAO {
*/ */
boolean updateDevice(Device device, int tenantId) throws DeviceManagementDAOException; boolean updateDevice(Device device, int tenantId) throws DeviceManagementDAOException;
Device getDevice(DeviceData deviceData, int tenantId) throws DeviceManagementDAOException;
/** /**
* This method is used to retrieve a device of a given device-identifier and tenant-id. * This method is used to retrieve a device of a given device-identifier and tenant-id.
* *
@ -446,13 +450,13 @@ public interface DeviceDAO {
* This method is used to retrieve current enrollment of a given device and user. * This method is used to retrieve current enrollment of a given device and user.
* *
* @param deviceId device id. * @param deviceId device id.
* @param currentUser user name. * @param request {@link PaginationRequest}
* @param tenantId tenant id. * @param tenantId tenant id.
* @return returns EnrolmentInfo object. * @return returns EnrolmentInfo object.
* @throws DeviceManagementDAOException * @throws DeviceManagementDAOException if SQL error occurred while processing the query.
*/ */
EnrolmentInfo getEnrolment(DeviceIdentifier deviceId, String currentUser, EnrolmentInfo getEnrolment(DeviceIdentifier deviceId, PaginationRequest request, int tenantId)
int tenantId) throws DeviceManagementDAOException; throws DeviceManagementDAOException;
/** /**
* This method is used to retrieve current active enrollment of a given device and tenant id. * This method is used to retrieve current active enrollment of a given device and tenant id.
@ -562,4 +566,18 @@ public interface DeviceDAO {
*/ */
List<DeviceLocationHistory> getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, long to) List<DeviceLocationHistory> getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, long to)
throws DeviceManagementDAOException; throws DeviceManagementDAOException;
/**
* This method is used to get the details of subscribed devices.
*
* @param deviceIds device ids of the subscribed devices.
* @param tenantId Id of the current tenant.
* @param offsetValue offset value for get paginated request.
* @param limitValue limit value for get paginated request.
* @param status status of the devices.
* @return devices - subscribed device details list
* @throws {@link DeviceManagementDAOException} if connections establishment fails.
*/
List<Device> getSubscribedDevices(int offsetValue, int limitValue, List<Integer> deviceIds,
int tenantId, String status) throws DeviceManagementDAOException;
} }

@ -36,6 +36,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl; package org.wso2.carbon.device.mgt.core.dao.impl;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
@ -44,6 +45,7 @@ import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceData;
import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
@ -65,7 +67,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.StringJoiner; import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractDeviceDAOImpl implements DeviceDAO { public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
@ -139,6 +140,84 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
} }
} }
@Override
public Device getDevice(DeviceData deviceData, int tenantId) throws DeviceManagementDAOException {
Device device = null;
try {
Connection conn = this.getConnection();
String sql = "SELECT "
+ "d1.ID AS DEVICE_ID, "
+ "d1.DESCRIPTION, "
+ "d1.NAME AS DEVICE_NAME, "
+ "d1.DEVICE_TYPE, "
+ "d1.DEVICE_IDENTIFICATION, "
+ "e.OWNER, "
+ "e.OWNERSHIP, "
+ "e.STATUS, "
+ "e.DATE_OF_LAST_UPDATE, "
+ "e.DATE_OF_ENROLMENT, "
+ "e.ID AS ENROLMENT_ID "
+ "FROM DM_ENROLMENT e, "
+ "(SELECT "
+ "d.ID, "
+ "d.DESCRIPTION, "
+ "d.NAME, "
+ "t.NAME AS DEVICE_TYPE, "
+ "d.DEVICE_IDENTIFICATION "
+ "FROM DM_DEVICE d, DM_DEVICE_TYPE t, DM_DEVICE_DETAIL dt "
+ "WHERE "
+ "t.NAME = ? AND "
+ "t.ID = d.DEVICE_TYPE_ID AND "
+ "d.DEVICE_IDENTIFICATION = ? AND "
+ "d.TENANT_ID = ? AND "
+ "dt.DEVICE_ID = d.ID";
if (deviceData.getLastModifiedDate() != null) {
sql += " AND dt.UPDATE_TIMESTAMP > ?";
}
sql += ") d1 WHERE d1.ID = e.DEVICE_ID AND ";
if (!StringUtils.isBlank(deviceData.getDeviceOwner())) {
sql += "e.OWNER = ? AND ";
}
if (!StringUtils.isBlank(deviceData.getDeviceOwnership())) {
sql += "e.OWNERSHIP = ? AND ";
}
sql += "TENANT_ID = ? ORDER BY e.DATE_OF_LAST_UPDATE DESC";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
int paramIndx = 1;
stmt.setString(paramIndx++, deviceData.getDeviceIdentifier().getType());
stmt.setString(paramIndx++, deviceData.getDeviceIdentifier().getId());
stmt.setInt(paramIndx++, tenantId);
if (deviceData.getLastModifiedDate() != null) {
stmt.setLong(paramIndx++, deviceData.getLastModifiedDate().getTime());
}
if (!StringUtils.isBlank(deviceData.getDeviceOwner())) {
stmt.setString(paramIndx++, deviceData.getDeviceOwner());
}
if (!StringUtils.isBlank(deviceData.getDeviceOwnership())) {
stmt.setString(paramIndx++, deviceData.getDeviceOwnership());
}
stmt.setInt(paramIndx, tenantId);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
device = DeviceManagementDAOUtil.loadMatchingDevice(rs, false);
}
}
}
} catch (SQLException e) {
String msg = "Error occurred while getting device data for device identifier "
+ deviceData.getDeviceIdentifier().getId() + " and device type "
+ deviceData.getDeviceIdentifier().getType();
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
}
return device;
}
@Override @Override
public Device getDevice(DeviceIdentifier deviceIdentifier, int tenantId) throws DeviceManagementDAOException { public Device getDevice(DeviceIdentifier deviceIdentifier, int tenantId) throws DeviceManagementDAOException {
Connection conn; Connection conn;
@ -239,7 +318,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " + "e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " +
"t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE " + "t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE " +
"t.NAME = ? AND t.ID = d.DEVICE_TYPE_ID AND d.DEVICE_IDENTIFICATION = ? AND d.TENANT_ID = ?) d1 WHERE d1.ID = e.DEVICE_ID " + "t.NAME = ? AND t.ID = d.DEVICE_TYPE_ID AND d.DEVICE_IDENTIFICATION = ? AND d.TENANT_ID = ?) d1 WHERE d1.ID = e.DEVICE_ID " +
"AND TENANT_ID = ? AND e.OWNER = ?"; "AND TENANT_ID = ? AND e.OWNER = ? ORDER BY e.DATE_OF_LAST_UPDATE DESC";
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceIdentifier.getType()); stmt.setString(1, deviceIdentifier.getType());
stmt.setString(2, deviceIdentifier.getId()); stmt.setString(2, deviceIdentifier.getId());
@ -508,7 +587,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " + "e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " +
"t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t, DM_DEVICE_DETAIL dt " + "t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t, DM_DEVICE_DETAIL dt " +
"WHERE t.NAME = ? AND t.ID = d.DEVICE_TYPE_ID AND d.DEVICE_IDENTIFICATION = ? AND d.TENANT_ID = ? AND dt.DEVICE_ID = d.ID " + "WHERE t.NAME = ? AND t.ID = d.DEVICE_TYPE_ID AND d.DEVICE_IDENTIFICATION = ? AND d.TENANT_ID = ? AND dt.DEVICE_ID = d.ID " +
"AND dt.UPDATE_TIMESTAMP > ?) d1 WHERE d1.ID = e.DEVICE_ID AND TENANT_ID = ? AND e.OWNER = ?"; "AND dt.UPDATE_TIMESTAMP > ?) d1 WHERE d1.ID = e.DEVICE_ID AND TENANT_ID = ? AND e.OWNER = ? ORDER BY e.DATE_OF_LAST_UPDATE DESC";
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceIdentifier.getType()); stmt.setString(1, deviceIdentifier.getType());
stmt.setString(2, deviceIdentifier.getId()); stmt.setString(2, deviceIdentifier.getId());
@ -1293,36 +1372,54 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
} }
@Override @Override
public EnrolmentInfo getEnrolment(DeviceIdentifier deviceId, String currentOwner, public EnrolmentInfo getEnrolment(DeviceIdentifier deviceId, PaginationRequest request, int tenantId)
int tenantId) throws DeviceManagementDAOException { throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
EnrolmentInfo enrolmentInfo = null; EnrolmentInfo enrolmentInfo = null;
try { try {
conn = this.getConnection(); Connection conn = this.getConnection();
String sql = "SELECT ID AS ENROLMENT_ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, DATE_OF_ENROLMENT, " + String sql = "SELECT "
"DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = (SELECT d.ID " + + "ID AS ENROLMENT_ID, "
+ "DEVICE_ID, "
+ "OWNER, "
+ "OWNERSHIP, "
+ "STATUS, "
+ "DATE_OF_ENROLMENT, "
+ "DATE_OF_LAST_UPDATE, "
+ "TENANT_ID "
+ "FROM DM_ENROLMENT "
+ "WHERE "
+ "DEVICE_ID = (SELECT d.ID " +
"FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.DEVICE_TYPE_ID = t.ID " + "FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.DEVICE_TYPE_ID = t.ID " +
"AND d.DEVICE_IDENTIFICATION = ? AND t.NAME = ? AND d.TENANT_ID = ?) " + "AND d.DEVICE_IDENTIFICATION = ? AND t.NAME = ? AND d.TENANT_ID = ?) "
"AND OWNER = ? AND TENANT_ID = ?"; + "AND OWNER = ? ";
stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceId.getId()); if (!StringUtils.isBlank(request.getOwnership())) {
stmt.setString(2, deviceId.getType()); sql += "AND OWNERSHIP = ? ";
stmt.setInt(3, tenantId); }
stmt.setString(4, currentOwner); sql += "AND TENANT_ID = ?";
stmt.setInt(5, tenantId); int paramIdx = 1;
rs = stmt.executeQuery(); try (PreparedStatement stmt = conn.prepareStatement(sql)) {
if (rs.next()) { stmt.setString(paramIdx++, deviceId.getId());
enrolmentInfo = DeviceManagementDAOUtil.loadMatchingEnrolment(rs); stmt.setString(paramIdx++, deviceId.getType());
stmt.setInt(paramIdx++, tenantId);
stmt.setString(paramIdx++, request.getOwner());
if (!StringUtils.isBlank(request.getOwnership())) {
stmt.setString(paramIdx++, request.getOwnership());
}
stmt.setInt(paramIdx, tenantId);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
enrolmentInfo = DeviceManagementDAOUtil.loadMatchingEnrolment(rs);
}
}
} }
return enrolmentInfo;
} catch (SQLException e) { } catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + String msg = "Error occurred while retrieving the enrolment " +
"information of user '" + currentOwner + "' upon device '" + deviceId + "'", e); "information of user '" + request.getOwner() + "' upon device '" + deviceId + "'";
} finally { log.error(msg, e);
DeviceManagementDAOUtil.cleanupResources(stmt, rs); throw new DeviceManagementDAOException(msg, e);
} }
return enrolmentInfo;
} }
@Override @Override

@ -34,6 +34,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.StringJoiner;
/** /**
* This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax. * This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax.
@ -583,6 +584,67 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices; return devices;
} }
@Override
public List<Device> getSubscribedDevices(int offsetValue, int limitValue,
List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
Connection conn;
try {
conn = this.getConnection();
int index = 1;
boolean isStatusProvided = false;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"f.ID AS DEVICE_ID, f.NAME AS DEVICE_NAME, f.DESCRIPTION AS DESCRIPTION, " +
"f.DEVICE_TYPE_ID, f.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " +
"e.ID AS ENROLMENT_ID, e.OWNER, e.OWNERSHIP, e.DATE_OF_ENROLMENT, " +
"e.DATE_OF_LAST_UPDATE, e.STATUS, t.NAME AS DEVICE_TYPE " +
"FROM DM_ENROLMENT AS e,DM_DEVICE AS f, DM_DEVICE_TYPE t "+
"WHERE " +
"e.DEVICE_ID=f.ID AND " +
"e.DEVICE_ID IN (", ") AND e.TENANT_ID=?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
if (status != null && !status.isEmpty()) {
query = query + " AND e.STATUS=?";
isStatusProvided = true;
}
query = query + " LIMIT ?,?";
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (isStatusProvided) {
ps.setString(index++, status);
}
ps.setInt(index++, offsetValue);
ps.setInt(index, limitValue);
try (ResultSet rs = ps.executeQuery()) {
List<Device> devices = new ArrayList<>();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDevice(rs));
}
return devices;
}
}
} catch (SQLException e) {
String msg = "Error occurred while retrieving information of all registered devices " +
"according to device ids and the limit area.";
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection(); return DeviceManagementDAOFactory.getConnection();
} }

@ -37,6 +37,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.StringJoiner;
/** /**
* This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax. * This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax.
@ -588,6 +589,67 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices; return devices;
} }
@Override
public List<Device> getSubscribedDevices(int offsetValue, int limitValue,
List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
Connection conn;
try {
conn = this.getConnection();
int index = 1;
boolean isStatusProvided = false;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"f.ID AS DEVICE_ID, f.NAME AS DEVICE_NAME, f.DESCRIPTION AS DESCRIPTION, " +
"f.DEVICE_TYPE_ID, f.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " +
"e.ID AS ENROLMENT_ID, e.OWNER, e.OWNERSHIP, e.DATE_OF_ENROLMENT, " +
"e.DATE_OF_LAST_UPDATE, e.STATUS, t.NAME AS DEVICE_TYPE " +
"FROM DM_ENROLMENT AS e,DM_DEVICE AS f, DM_DEVICE_TYPE t " +
"WHERE " +
"e.DEVICE_ID=f.ID AND " +
"e.DEVICE_ID IN (", ") AND e.TENANT_ID=?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
if (status != null && !status.isEmpty()) {
query = query + " AND e.STATUS=?";
isStatusProvided = true;
}
query = query + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (isStatusProvided) {
ps.setString(index++, status);
}
ps.setInt(index++, offsetValue);
ps.setInt(index, limitValue);
try (ResultSet rs = ps.executeQuery()) {
List<Device> devices = new ArrayList<>();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDevice(rs));
}
return devices;
}
}
} catch (SQLException e) {
String msg = "Error occurred while retrieving information of all registered devices " +
"according to device ids and the limit area.";
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection(); return DeviceManagementDAOFactory.getConnection();
} }

@ -34,6 +34,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.StringJoiner;
/** /**
* This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax. * This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax.
@ -566,6 +567,67 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices; return devices;
} }
@Override
public List<Device> getSubscribedDevices(int offsetValue, int limitValue,
List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
Connection conn;
try {
conn = this.getConnection();
int index = 1;
boolean isStatusProvided = false;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"f.ID AS DEVICE_ID, f.NAME AS DEVICE_NAME, f.DESCRIPTION AS DESCRIPTION, " +
"f.DEVICE_TYPE_ID, f.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " +
"e.ID AS ENROLMENT_ID, e.OWNER, e.OWNERSHIP, e.DATE_OF_ENROLMENT, " +
"e.DATE_OF_LAST_UPDATE, e.STATUS, t.NAME AS DEVICE_TYPE " +
"FROM DM_ENROLMENT AS e,DM_DEVICE AS f, DM_DEVICE_TYPE t "+
"WHERE " +
"e.DEVICE_ID=f.ID AND " +
"e.DEVICE_ID IN (", ") AND e.TENANT_ID=?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
if (status != null && !status.isEmpty()) {
query = query + " AND e.STATUS=?";
isStatusProvided = true;
}
query = query + " LIMIT ? OFFSET ?";
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (isStatusProvided) {
ps.setString(index++, status);
}
ps.setInt(index++, offsetValue);
ps.setInt(index, limitValue);
try (ResultSet rs = ps.executeQuery()) {
List<Device> devices = new ArrayList<>();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDevice(rs));
}
return devices;
}
}
} catch (SQLException e) {
String msg = "Error occurred while retrieving information of all registered devices " +
"according to device ids and the limit area.";
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection(); return DeviceManagementDAOFactory.getConnection();
} }

@ -34,6 +34,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.StringJoiner;
/** /**
* This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax. * This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax.
@ -521,6 +522,67 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices; return devices;
} }
@Override
public List<Device> getSubscribedDevices(int offsetValue, int limitValue,
List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
Connection conn;
try {
conn = this.getConnection();
int index = 1;
boolean isStatusProvided = false;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"f.ID AS DEVICE_ID, f.NAME AS DEVICE_NAME, f.DESCRIPTION AS DESCRIPTION, " +
"f.DEVICE_TYPE_ID, f.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " +
"e.ID AS ENROLMENT_ID, e.OWNER, e.OWNERSHIP, e.DATE_OF_ENROLMENT, " +
"e.DATE_OF_LAST_UPDATE, e.STATUS, t.NAME AS DEVICE_TYPE " +
"FROM DM_ENROLMENT AS e,DM_DEVICE AS f, DM_DEVICE_TYPE t "+
"WHERE " +
"e.DEVICE_ID=f.ID AND " +
"e.DEVICE_ID IN (", ") AND e.TENANT_ID=?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
if (status != null && !status.isEmpty()) {
query = query + " AND e.STATUS=?";
isStatusProvided = true;
}
query = query + " LIMIT ?,?";
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (isStatusProvided) {
ps.setString(index++, status);
}
ps.setInt(index++, offsetValue);
ps.setInt(index, limitValue);
try (ResultSet rs = ps.executeQuery()) {
List<Device> devices = new ArrayList<>();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDevice(rs));
}
return devices;
}
}
} catch (SQLException e) {
String msg = "Error occurred while retrieving information of all registered devices " +
"according to device ids and the limit area.";
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection(); return DeviceManagementDAOFactory.getConnection();
} }

@ -458,7 +458,12 @@ public class OperationManagerImpl implements OperationManager {
deviceId.getType() + "' device, which carries the identifier '" + deviceId.getType() + "' device, which carries the identifier '" +
deviceId.getId() + "' of owner '" + owner + "'"); deviceId.getId() + "' of owner '" + owner + "'");
} }
EnrolmentInfo enrolmentInfo = this.getEnrolmentInfo(deviceId, owner); EnrolmentInfo enrolmentInfo = this.getEnrolmentInfo(deviceId, request);
if (enrolmentInfo == null){
throw new OperationManagementException("Enrollment info not found for given device which has device "
+ "Identifier:" + deviceId.getId() + " and device type: " + deviceId.getType() + "Further, device "
+ "is own to: " + owner);
}
int enrolmentId = enrolmentInfo.getId(); int enrolmentId = enrolmentInfo.getId();
try { try {
OperationManagementDAOFactory.openConnection(); OperationManagementDAOFactory.openConnection();
@ -1072,33 +1077,34 @@ public class OperationManagerImpl implements OperationManager {
return isUserAuthorized; return isUserAuthorized;
} }
private EnrolmentInfo getEnrolmentInfo(DeviceIdentifier deviceId, String owner) throws OperationManagementException { private EnrolmentInfo getEnrolmentInfo(DeviceIdentifier deviceId, PaginationRequest request)
throws OperationManagementException {
EnrolmentInfo enrolmentInfo = null; EnrolmentInfo enrolmentInfo = null;
try { try {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
String user = this.getUser(); String user = this.getUser();
DeviceManagementDAOFactory.openConnection(); DeviceManagementDAOFactory.openConnection();
if (this.isSameUser(user, owner)) { if (this.isSameUser(user, request.getOwner())) {
enrolmentInfo = deviceDAO.getEnrolment(deviceId, owner, tenantId); enrolmentInfo = deviceDAO.getEnrolment(deviceId, request, tenantId);
} else { } else {
boolean isAdminUser = DeviceManagementDataHolder.getInstance().getDeviceAccessAuthorizationService(). boolean isAdminUser = DeviceManagementDataHolder.getInstance().getDeviceAccessAuthorizationService().
isDeviceAdminUser(); isDeviceAdminUser();
if (isAdminUser) { if (isAdminUser) {
enrolmentInfo = deviceDAO.getEnrolment(deviceId, owner, tenantId); enrolmentInfo = deviceDAO.getEnrolment(deviceId, request, tenantId);
} }
//TODO : Add a check for group admin if this fails //TODO : Add a check for group admin if this fails
} }
} catch (DeviceManagementDAOException e) { } catch (DeviceManagementDAOException e) {
throw new OperationManagementException("Error occurred while retrieving enrollment data of '" + throw new OperationManagementException("Error occurred while retrieving enrollment data of '" +
deviceId.getType() + "' device carrying the identifier '" + deviceId.getType() + "' device carrying the identifier '" +
deviceId.getId() + "' of owner '" + owner + "'", e); deviceId.getId() + "' of owner '" + request.getOwner() + "'", e);
} catch (SQLException e) { } catch (SQLException e) {
throw new OperationManagementException( throw new OperationManagementException(
"Error occurred while opening a connection to the data source", e); "Error occurred while opening a connection to the data source", e);
} catch (DeviceAccessAuthorizationException e) { } catch (DeviceAccessAuthorizationException e) {
throw new OperationManagementException("Error occurred while checking the device access permissions for '" + throw new OperationManagementException("Error occurred while checking the device access permissions for '" +
deviceId.getType() + "' device carrying the identifier '" + deviceId.getType() + "' device carrying the identifier '" +
deviceId.getId() + "' of owner '" + owner + "'", e); deviceId.getId() + "' of owner '" + request.getOwner() + "'", e);
} finally { } finally {
DeviceManagementDAOFactory.closeConnection(); DeviceManagementDAOFactory.closeConnection();
} }

@ -56,6 +56,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManageme
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
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.device.details.DeviceLocationHistory; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.device.details.DeviceData;
import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.device.mgt.common.license.mgt.License;
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;
@ -262,6 +263,17 @@ public interface DeviceManagementProviderService {
*/ */
Device getDevice(DeviceIdentifier deviceId, Date since, boolean requireDeviceInfo) throws DeviceManagementException; Device getDevice(DeviceIdentifier deviceId, Date since, boolean requireDeviceInfo) throws DeviceManagementException;
/***
*
* @param deviceData Device data,
* @param requireDeviceInfo A boolean indicating whether the device-info (location, app-info etc) is also required
* along with the device data.
* @return {@link Device}, null when device is not available.
* @throws {@link DeviceManagementException}
*/
Device getDevice(DeviceData deviceData, boolean requireDeviceInfo) throws DeviceManagementException;
/** /**
* Retrieves a list of devices based on a given criteria of properties * Retrieves a list of devices based on a given criteria of properties
* *
@ -759,7 +771,6 @@ public interface DeviceManagementProviderService {
DeviceTypeVersion getDeviceTypeVersion(String deviceTypeName, String version) throws DeviceTypeVersion getDeviceTypeVersion(String deviceTypeName, String version) throws
DeviceManagementException; DeviceManagementException;
/** /**
* Retrieves a list of configurations of a specific device * Retrieves a list of configurations of a specific device
* using the device's properties * using the device's properties
@ -782,4 +793,18 @@ public interface DeviceManagementProviderService {
* @return tru if device transferee, otherwise false * @return tru if device transferee, otherwise false
*/ */
List<String> transferDeviceToTenant(DeviceTransferRequest deviceTransferRequest) throws DeviceManagementException, DeviceNotFoundException; List<String> transferDeviceToTenant(DeviceTransferRequest deviceTransferRequest) throws DeviceManagementException, DeviceNotFoundException;
/**
* This method retrieves a list of subscribed devices.
*
* @param devicesIds devices ids of the subscribed devices.
* @param offsetValue offset value for get paginated request.
* @param limitValue limit value for get paginated request.
* @param status status of the devices.
* @return {@link PaginationResult}
* @throws {@link DeviceManagementException} if any service level or DAO level error occurs.
*/
PaginationResult getAppSubscribedDevices(int offsetValue, int limitValue,
List<Integer> devicesIds, String status)
throws DeviceManagementException;
} }

@ -77,6 +77,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManageme
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
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.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.DeviceLocationHistory;
@ -1242,6 +1243,54 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return device; return device;
} }
@Override
public Device getDevice(DeviceData deviceData, boolean requireDeviceInfo)
throws DeviceManagementException {
if (deviceData.getDeviceIdentifier() == null) {
String msg = "Received null device identifier for method getDevice";
log.error(msg);
throw new DeviceManagementException(msg);
}
if (log.isDebugEnabled()) {
log.debug("Get device by device identifier :" + deviceData.getDeviceIdentifier().getId() + " of type '"
+ deviceData.getDeviceIdentifier().getType() + "' and requiredDeviceInfo: " + requireDeviceInfo);
}
Device device = null;
int tenantId = this.getTenantId();
try {
DeviceManagementDAOFactory.openConnection();
device = deviceDAO.getDevice(deviceData, tenantId);
if (device == null) {
String msg =
"No device is found upon the type '" + deviceData.getDeviceIdentifier().getType() + "' and id '"
+ deviceData.getDeviceIdentifier().getId() + "'";
if (log.isDebugEnabled()) {
log.debug(msg);
}
return null;
}
} catch (DeviceManagementDAOException e) {
String msg =
"Error occurred while obtaining the device for '" + deviceData.getDeviceIdentifier().getId() + "'";
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);
throw new DeviceManagementException(msg, e);
} catch (Exception e) {
String msg = "Error occurred in getDevice: " + deviceData.getDeviceIdentifier().getId();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
if (requireDeviceInfo) {
return this.getAllDeviceInfo(device);
}
return device;
}
@Override @Override
public List<Device> getDevicesBasedOnProperties(Map deviceProps) throws DeviceManagementException { public List<Device> getDevicesBasedOnProperties(Map deviceProps) throws DeviceManagementException {
@ -1718,9 +1767,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
@Override @Override
public PaginationResult getOperations(DeviceIdentifier deviceId, PaginationRequest request) public PaginationResult getOperations(DeviceIdentifier deviceId, PaginationRequest request)
throws OperationManagementException { throws OperationManagementException {
request = DeviceManagerUtil.validateOperationListPageSize(request);
return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()) return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId())
.getOperations(deviceId, request); .getOperations(deviceId, DeviceManagerUtil.validateOperationListPageSize(request));
} }
@Override @Override
@ -3665,4 +3713,39 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
deviceConfiguration.setDeviceOwner(deviceOwner); deviceConfiguration.setDeviceOwner(deviceOwner);
return deviceConfiguration; return deviceConfiguration;
} }
@Override
public PaginationResult getAppSubscribedDevices(int offsetValue, int limitValue,
List<Integer> devicesIds, String status)
throws DeviceManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (log.isDebugEnabled()) {
log.debug("Getting all devices details for device ids: " + devicesIds);
}
PaginationResult paginationResult = new PaginationResult();
int count;
List<Device> SubscribedDeviceDetails;
try {
DeviceManagementDAOFactory.openConnection();
SubscribedDeviceDetails = deviceDAO
.getSubscribedDevices(offsetValue, limitValue, devicesIds, tenantId, status);
count = SubscribedDeviceDetails.size();
} catch (DeviceManagementDAOException e) {
String msg = "Error occurred while retrieving device list for device ids " + devicesIds;
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while opening a connection to the data source";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
paginationResult.setData(getAllDeviceInfo(SubscribedDeviceDetails));
paginationResult.setRecordsFiltered(count);
paginationResult.setRecordsTotal(count);
return paginationResult;
}
} }

@ -55,6 +55,7 @@ public class OperationManagementNegativeDBOperationTest extends BaseDeviceManage
private static final String DEVICE_ID_PREFIX = "NEGDB_OP-TEST-DEVICE-ID-"; private static final String DEVICE_ID_PREFIX = "NEGDB_OP-TEST-DEVICE-ID-";
private static final int NO_OF_DEVICES = 5; private static final int NO_OF_DEVICES = 5;
private static final String ADMIN_USER = "admin"; private static final String ADMIN_USER = "admin";
private static final String OWNSERSHIP = "BYOD";
private List<DeviceIdentifier> deviceIds = new ArrayList<>(); private List<DeviceIdentifier> deviceIds = new ArrayList<>();
private OperationManager operationMgtService; private OperationManager operationMgtService;
@ -111,6 +112,7 @@ public class OperationManagementNegativeDBOperationTest extends BaseDeviceManage
PaginationRequest request = new PaginationRequest(1, 2); PaginationRequest request = new PaginationRequest(1, 2);
request.setDeviceType(DEVICE_TYPE); request.setDeviceType(DEVICE_TYPE);
request.setOwner(ADMIN_USER); request.setOwner(ADMIN_USER);
request.setOwnership(OWNSERSHIP);
this.dataSource.setThrowException(true); this.dataSource.setThrowException(true);
try { try {
this.operationMgtService.getOperations(this.deviceIds.get(0), request); this.operationMgtService.getOperations(this.deviceIds.get(0), request);

@ -57,6 +57,7 @@ public class OperationManagementNoDBSchemaTests extends BaseDeviceManagementTest
private static final String COMMAND_OPERATON_CODE = "COMMAND-TEST"; private static final String COMMAND_OPERATON_CODE = "COMMAND-TEST";
private static final int NO_OF_DEVICES = 5; private static final int NO_OF_DEVICES = 5;
private static final String ADMIN_USER = "admin"; private static final String ADMIN_USER = "admin";
private static final String OWNERSHIP = "BYOD";
private List<DeviceIdentifier> deviceIds = new ArrayList<>(); private List<DeviceIdentifier> deviceIds = new ArrayList<>();
private OperationManager operationMgtService; private OperationManager operationMgtService;
@ -124,6 +125,7 @@ public class OperationManagementNoDBSchemaTests extends BaseDeviceManagementTest
PaginationRequest request = new PaginationRequest(1, 2); PaginationRequest request = new PaginationRequest(1, 2);
request.setDeviceType(DEVICE_TYPE); request.setDeviceType(DEVICE_TYPE);
request.setOwner(ADMIN_USER); request.setOwner(ADMIN_USER);
request.setOwnership(OWNERSHIP);
for (DeviceIdentifier deviceIdentifier : deviceIds) { for (DeviceIdentifier deviceIdentifier : deviceIds) {
this.operationMgtService.getOperations(deviceIdentifier, request); this.operationMgtService.getOperations(deviceIdentifier, request);
} }

@ -75,6 +75,7 @@ public class OperationManagementTests extends BaseDeviceManagementTest {
private static final String ADMIN_USER = "admin"; private static final String ADMIN_USER = "admin";
private static final String NON_ADMIN_USER = "test"; private static final String NON_ADMIN_USER = "test";
private static final String INVALID_DEVICE = "ThisIsInvalid"; private static final String INVALID_DEVICE = "ThisIsInvalid";
private static final String OWNERSHIP = "BYOD";
private List<DeviceIdentifier> deviceIds = new ArrayList<>(); private List<DeviceIdentifier> deviceIds = new ArrayList<>();
private OperationManager operationMgtService; private OperationManager operationMgtService;
@ -286,6 +287,7 @@ public class OperationManagementTests extends BaseDeviceManagementTest {
PaginationRequest request = new PaginationRequest(1, 2); PaginationRequest request = new PaginationRequest(1, 2);
request.setDeviceType(DEVICE_TYPE); request.setDeviceType(DEVICE_TYPE);
request.setOwner(ADMIN_USER); request.setOwner(ADMIN_USER);
request.setOwnership(OWNERSHIP);
for (DeviceIdentifier deviceIdentifier : deviceIds) { for (DeviceIdentifier deviceIdentifier : deviceIds) {
PaginationResult result = this.operationMgtService.getOperations(deviceIdentifier, request); PaginationResult result = this.operationMgtService.getOperations(deviceIdentifier, request);
Assert.assertEquals(result.getRecordsFiltered(), 4); Assert.assertEquals(result.getRecordsFiltered(), 4);
@ -302,6 +304,7 @@ public class OperationManagementTests extends BaseDeviceManagementTest {
PaginationRequest request = new PaginationRequest(1, 2); PaginationRequest request = new PaginationRequest(1, 2);
request.setDeviceType(DEVICE_TYPE); request.setDeviceType(DEVICE_TYPE);
request.setOwner(ADMIN_USER); request.setOwner(ADMIN_USER);
request.setOwnership(OWNERSHIP);
for (DeviceIdentifier deviceIdentifier : deviceIds) { for (DeviceIdentifier deviceIdentifier : deviceIds) {
try { try {
this.operationMgtService.getOperations(deviceIdentifier, request); this.operationMgtService.getOperations(deviceIdentifier, request);
@ -540,6 +543,7 @@ public class OperationManagementTests extends BaseDeviceManagementTest {
PaginationRequest request = new PaginationRequest(1, 2); PaginationRequest request = new PaginationRequest(1, 2);
request.setDeviceType(DEVICE_TYPE); request.setDeviceType(DEVICE_TYPE);
request.setOwner(ADMIN_USER); request.setOwner(ADMIN_USER);
request.setOwnership(OWNERSHIP);
PaginationResult result = this.operationMgtService.getOperations PaginationResult result = this.operationMgtService.getOperations
(new DeviceIdentifier(INVALID_DEVICE, DEVICE_TYPE), request); (new DeviceIdentifier(INVALID_DEVICE, DEVICE_TYPE), request);
Assert.assertEquals(result.getRecordsFiltered(), 4); Assert.assertEquals(result.getRecordsFiltered(), 4);

@ -29,12 +29,14 @@ if (uriMatcher.match("/{context}/api/operation/paginate")) {
var deviceType = request.getParameter("deviceType"); var deviceType = request.getParameter("deviceType");
var deviceId = request.getParameter("deviceId"); var deviceId = request.getParameter("deviceId");
var owner = request.getParameter("owner"); var owner = request.getParameter("owner");
var ownership = request.getParameter("ownership");
var index = request.getParameter("start"); var index = request.getParameter("start");
var length = request.getParameter("length"); var length = request.getParameter("length");
var search = request.getParameter("search[value]"); var search = request.getParameter("search[value]");
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
"/devices/" + deviceType + "/" + deviceId + "/operations?owner=" + owner + "&offset=" + index + "&limit=" + length; "/devices/" + deviceType + "/" + deviceId + "/operations?owner=" + owner + "&ownership=" + ownership +
"&offset=" + index + "&limit=" + length;
serviceInvokers.XMLHttp.get( serviceInvokers.XMLHttp.get(
restAPIEndpoint, restAPIEndpoint,

@ -63,7 +63,7 @@ deviceModule = function () {
/* /*
@Updated @Updated
*/ */
publicMethods.viewDevice = function (deviceType, deviceId, owner) { publicMethods.viewDevice = function (deviceType, deviceId, owner, ownership) {
var carbonUser = session.get(constants["USER_SESSION_KEY"]); var carbonUser = session.get(constants["USER_SESSION_KEY"]);
if (!carbonUser) { if (!carbonUser) {
log.error("User object was not found in the session"); log.error("User object was not found in the session");
@ -114,7 +114,12 @@ deviceModule = function () {
utility.startTenantFlow(carbonUser); utility.startTenantFlow(carbonUser);
var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId; var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId;
if (owner) { if (owner) {
url = url + "?owner=" + owner; url = url + "?owner=" + owner;
if (ownership){
url = url + "&ownership=" + ownership;
}
} else if (ownership){
url = url + "?ownership=" + ownership;
} }
return serviceInvokers.XMLHttp.get( return serviceInvokers.XMLHttp.get(
url, url,

@ -342,7 +342,8 @@ function loadDevices(searchType, searchParam) {
data: 'ownership', data: 'ownership',
class: 'remove-padding-top viewEnabledIcon', class: 'remove-padding-top viewEnabledIcon',
render: function (status, type, row, meta) { render: function (status, type, row, meta) {
if (getDeviceTypeCategory(row.deviceType) == 'mobile') { if (getDeviceTypeCategory(row.deviceType) === 'mobile'
|| getDeviceTypeCategory(row.deviceType) === 'hybrid') {
return row.ownership; return row.ownership;
} else { } else {
return null; return null;
@ -422,17 +423,6 @@ function loadDevices(searchType, searchParam) {
]; ];
var fnCreatedRow = function (row, data, dataIndex) { var fnCreatedRow = function (row, data, dataIndex) {
if(data.status != "REMOVED"){
$(row).attr('data-type', 'selectable');
}else{
$(row).attr('data-type', 'non-selectable');
}
$(row).attr('data-deviceid', htmlspecialchars(data.deviceIdentifier));
$(row).attr('data-devicetype', htmlspecialchars(data.deviceType));
$(row).attr('data-url', context + '/device/' + htmlspecialchars(data.deviceType) + '?id='
+ htmlspecialchars(data.deviceIdentifier) + '&owner=' + htmlspecialchars(data.userPattern)) ;
var model = htmlspecialchars(getPropertyValue(data.properties, 'DEVICE_MODEL')); var model = htmlspecialchars(getPropertyValue(data.properties, 'DEVICE_MODEL'));
var vendor = htmlspecialchars(getPropertyValue(data.properties, 'VENDOR')); var vendor = htmlspecialchars(getPropertyValue(data.properties, 'VENDOR'));
var owner = htmlspecialchars(data.userPattern); var owner = htmlspecialchars(data.userPattern);
@ -440,6 +430,10 @@ function loadDevices(searchType, searchParam) {
var ownership = htmlspecialchars(data.ownership); var ownership = htmlspecialchars(data.ownership);
var deviceType = htmlspecialchars(data.deviceType); var deviceType = htmlspecialchars(data.deviceType);
var category = getDeviceTypeCategory(deviceType); var category = getDeviceTypeCategory(deviceType);
$(row).attr('data-deviceid', htmlspecialchars(data.deviceIdentifier));
$(row).attr('data-devicetype', deviceType);
$(row).attr('data-url', context + '/device/' + htmlspecialchars(data.deviceType) + '?id='
+ htmlspecialchars(data.deviceIdentifier) + '&owner=' + owner + '&ownership=' + ownership) ;
$.each($('td', row), function (colIndex) { $.each($('td', row), function (colIndex) {
switch (colIndex) { switch (colIndex) {
case 1: case 1:
@ -462,7 +456,7 @@ function loadDevices(searchType, searchParam) {
$(this).attr('data-display', getDeviceTypeLabel(deviceType)); $(this).attr('data-display', getDeviceTypeLabel(deviceType));
break; break;
case 5: case 5:
if (category == 'mobile') { if (category === 'mobile' || category === 'hybrid') {
$(this).attr('data-grid-label', "Ownership"); $(this).attr('data-grid-label', "Ownership");
$(this).attr('data-search', ownership); $(this).attr('data-search', ownership);
$(this).attr('data-display', ownership); $(this).attr('data-display', ownership);

@ -24,6 +24,7 @@ function onRequest(context) {
var deviceType = context.uriParams.deviceType; var deviceType = context.uriParams.deviceType;
var deviceId = request.getParameter("id"); var deviceId = request.getParameter("id");
var owner = request.getParameter("owner"); var owner = request.getParameter("owner");
var ownership = request.getParameter("ownership");
var attributes = []; var attributes = [];
var featureList = []; var featureList = [];
var user = userModule.getCarbonUser(); var user = userModule.getCarbonUser();
@ -130,10 +131,10 @@ function onRequest(context) {
displayData.tenantDomain = tenantDomain; displayData.tenantDomain = tenantDomain;
if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) { if (deviceType && deviceId) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"]; var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId, owner); var device = deviceModule.viewDevice(deviceType, deviceId, owner, ownership);
if (device && device.status != "error") { if (device && device.status !== "error") {
displayData.device = device.content; displayData.device = device.content;
displayData.autoCompleteParams = autoCompleteParams; displayData.autoCompleteParams = autoCompleteParams;
displayData.encodedFeaturePayloads = ""; displayData.encodedFeaturePayloads = "";

@ -20,6 +20,7 @@ var deviceId = $(".device-id");
var deviceIdentifier = deviceId.data("deviceid"); var deviceIdentifier = deviceId.data("deviceid");
var deviceType = deviceId.data("type"); var deviceType = deviceId.data("type");
var deviceOwner = deviceId.data("owner"); var deviceOwner = deviceId.data("owner");
var deviceOwnership = deviceId.data("ownership");
$(document).ready(function() { $(document).ready(function() {
$(".panel-body").removeClass("hidden"); $(".panel-body").removeClass("hidden");
@ -86,7 +87,8 @@ function loadOperationsLog(update) {
data: { data: {
deviceId: deviceIdentifier, deviceId: deviceIdentifier,
deviceType: deviceType, deviceType: deviceType,
owner: deviceOwner owner: deviceOwner,
ownership: deviceOwnership
}, },
dataSrc: function(json) { dataSrc: function(json) {
$("#operations-spinner").addClass("hidden"); $("#operations-spinner").addClass("hidden");

@ -21,10 +21,11 @@ function onRequest(context) {
var deviceType = context["uriParams"]["deviceType"]; var deviceType = context["uriParams"]["deviceType"];
var deviceId = request.getParameter("id"); var deviceId = request.getParameter("id");
var owner = request.getParameter("owner"); var owner = request.getParameter("owner");
var ownership = request.getParameter("ownership");
var deviceViewData = {}; var deviceViewData = {};
if (deviceType && deviceId) { if (deviceType && deviceId) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"]; var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var response = deviceModule.viewDevice(deviceType, deviceId, owner); var response = deviceModule.viewDevice(deviceType, deviceId, owner, ownership);
if (response["status"] == "success") { if (response["status"] == "success") {
deviceViewData["deviceFound"] = true; deviceViewData["deviceFound"] = true;
deviceViewData["isAuthorized"] = true; deviceViewData["isAuthorized"] = true;

@ -458,6 +458,8 @@ var savePolicy = function (policy, isActive, serviceURL) {
payload["deviceGroups"] = policy["selectedGroups"]; payload["deviceGroups"] = policy["selectedGroups"];
} }
payload["policyType"] = "GENERAL";
invokerUtil.post( invokerUtil.post(
serviceURL, serviceURL,
payload, payload,

@ -155,4 +155,11 @@ public interface PolicyAdministratorPoint {
List<Profile> getProfiles() throws PolicyManagementException; List<Profile> getProfiles() throws PolicyManagementException;
int getPolicyCount() throws PolicyManagementException; int getPolicyCount() throws PolicyManagementException;
/**
* @param policyType type of the policy
* @return policy list of the specific type
* @throws PolicyManagementException
*/
List<Policy> getPolicies(String policyType) throws PolicyManagementException;
} }

@ -113,4 +113,13 @@ public interface PolicyCacheManager {
* @return - Id of the policy. * @return - Id of the policy.
*/ */
int getPolicyIdOfDevice(int deviceId); int getPolicyIdOfDevice(int deviceId);
/**
* This method will return the all policies belongs to the specific type.
*
* @param policyType - type of the policy
* @return - list of policies
* @throws PolicyManagementException
*/
List<Policy> getAllPolicies(String policyType) throws PolicyManagementException;
} }

@ -30,6 +30,7 @@ import org.wso2.carbon.policy.mgt.core.util.PolicyManagementConstants;
import org.wso2.carbon.policy.mgt.core.util.PolicyManagerUtil; import org.wso2.carbon.policy.mgt.core.util.PolicyManagerUtil;
import javax.cache.Cache; import javax.cache.Cache;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -74,31 +75,13 @@ public class PolicyCacheManagerImpl implements PolicyCacheManager {
@Override @Override
public List<Policy> getAllPolicies() throws PolicyManagementException { public List<Policy> getAllPolicies() throws PolicyManagementException {
Cache<Integer, List<Policy>> lCache = getPolicyListCache(); Cache<Integer, List<Policy>> lCache = getPolicyListCache();
if (!lCache.containsKey(1)) { updateCache(lCache);
PolicyManager policyManager = new PolicyManagerImpl();
this.addAllPolicies(policyManager.getPolicies());
}
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
List<Policy> cachedPolicy = lCache.get(1); showDebugLog(lCache);
for (Policy policy : cachedPolicy) {
log.debug("Policy id in cache .. : " + policy.getId() + " policy name : " + policy.
getPolicyName() + " Activated : " + policy.isActive());
List<String> users = policy.getUsers();
for (String user : users) {
log.debug("Users in cached policy : " + user);
}
List<String> roles = policy.getRoles();
for (String role : roles) {
log.debug("Roles in cached policy : " + role);
}
}
} }
lCache = getPolicyListCache();
return lCache.get(1); return lCache.get(1);
} }
@Override @Override
@ -218,4 +201,47 @@ public class PolicyCacheManagerImpl implements PolicyCacheManager {
return 0; return 0;
} }
@Override
public List<Policy> getAllPolicies(String policyType) throws PolicyManagementException {
Cache<Integer, List<Policy>> lCache = getPolicyListCache();
updateCache(lCache);
if (log.isDebugEnabled()) {
showDebugLog(lCache);
}
lCache = getPolicyListCache();
List<Policy> policyListByType = new ArrayList<>();
List<Policy> cachedPolicyList = lCache.get(1);
Iterator<Policy> iterator = cachedPolicyList.iterator();
while (iterator.hasNext()) {
Policy policy = iterator.next();
if (policy.getPolicyType().equals(policyType)) {
policyListByType.add(policy);
}
}
return policyListByType;
}
private void updateCache(Cache<Integer, List<Policy>> lCache) throws PolicyManagementException {
if (!lCache.containsKey(1)) {
PolicyManager policyManager = new PolicyManagerImpl();
this.addAllPolicies(policyManager.getPolicies());
}
}
private void showDebugLog(Cache<Integer, List<Policy>> lCache) {
List<Policy> cachedPolicy = lCache.get(1);
for (Policy policy : cachedPolicy) {
log.debug("Policy id in cache .. : " + policy.getId() + " policy name : " + policy.
getPolicyName() + " Activated : " + policy.isActive());
List<String> users = policy.getUsers();
for (String user : users) {
log.debug("Users in cached policy : " + user);
}
List<String> roles = policy.getRoles();
for (String role : roles) {
log.debug("Roles in cached policy : " + role);
}
}
}
} }

@ -150,4 +150,6 @@ public interface PolicyDAO {
HashMap<Integer, Integer> getAppliedPolicyIds() throws PolicyManagerDAOException; HashMap<Integer, Integer> getAppliedPolicyIds() throws PolicyManagerDAOException;
HashMap<Integer, Integer> getAppliedPolicyIdsDeviceIds() throws PolicyManagerDAOException; HashMap<Integer, Integer> getAppliedPolicyIdsDeviceIds() throws PolicyManagerDAOException;
List<Policy> getAllPolicies(String policyType) throws PolicyManagerDAOException;
} }

@ -979,21 +979,7 @@ public class PolicyDAOImpl implements PolicyDAO {
stmt.setInt(1, tenantId); stmt.setInt(1, tenantId);
resultSet = stmt.executeQuery(); resultSet = stmt.executeQuery();
while (resultSet.next()) { return this.extractPolicyListFromDbResult(resultSet, tenantId);
Policy policy = new Policy();
policy.setId(resultSet.getInt("ID"));
policy.setProfileId(resultSet.getInt("PROFILE_ID"));
policy.setPolicyName(resultSet.getString("NAME"));
policy.setTenantId(tenantId);
policy.setPriorityId(resultSet.getInt("PRIORITY"));
policy.setCompliance(resultSet.getString("COMPLIANCE"));
policy.setOwnershipType(resultSet.getString("OWNERSHIP_TYPE"));
policy.setUpdated(PolicyManagerUtil.convertIntToBoolean(resultSet.getInt("UPDATED")));
policy.setActive(PolicyManagerUtil.convertIntToBoolean(resultSet.getInt("ACTIVE")));
policy.setDescription(resultSet.getString("DESCRIPTION"));
policies.add(policy);
}
return policies;
} catch (SQLException e) { } catch (SQLException e) {
throw new PolicyManagerDAOException("Error occurred while reading the policies from the database", e); throw new PolicyManagerDAOException("Error occurred while reading the policies from the database", e);
} finally { } finally {
@ -1437,7 +1423,7 @@ public class PolicyDAOImpl implements PolicyDAO {
try { try {
conn = this.getConnection(); conn = this.getConnection();
String query = "INSERT INTO DM_POLICY (NAME, PROFILE_ID, TENANT_ID, PRIORITY, COMPLIANCE, OWNERSHIP_TYPE," + String query = "INSERT INTO DM_POLICY (NAME, PROFILE_ID, TENANT_ID, PRIORITY, COMPLIANCE, OWNERSHIP_TYPE," +
"UPDATED, ACTIVE, DESCRIPTION) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; "UPDATED, ACTIVE, DESCRIPTION, POLICY_TYPE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
stmt = conn.prepareStatement(query, new String[]{"id"}); stmt = conn.prepareStatement(query, new String[]{"id"});
stmt.setString(1, policy.getPolicyName()); stmt.setString(1, policy.getPolicyName());
@ -1449,6 +1435,7 @@ public class PolicyDAOImpl implements PolicyDAO {
stmt.setInt(7, 0); stmt.setInt(7, 0);
stmt.setInt(8, 0); stmt.setInt(8, 0);
stmt.setString(9, policy.getDescription()); stmt.setString(9, policy.getDescription());
stmt.setString(10, policy.getPolicyType());
int affectedRows = stmt.executeUpdate(); int affectedRows = stmt.executeUpdate();
@ -1704,4 +1691,57 @@ public class PolicyDAOImpl implements PolicyDAO {
return devicePolicyIds; return devicePolicyIds;
} }
@Override
public List<Policy> getAllPolicies(String policyType) throws PolicyManagerDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
conn = this.getConnection();
String query = "SELECT ID, " +
"PROFILE_ID, " +
"NAME, " +
"PRIORITY, " +
"COMPLIANCE, " +
"OWNERSHIP_TYPE, " +
"UPDATED, " +
"ACTIVE, " +
"DESCRIPTION, " +
"POLICY_TYPE "+
"FROM DM_POLICY WHERE TENANT_ID = ? AND POLICY_TYPE = ?";
stmt = conn.prepareStatement(query);
stmt.setInt(1, tenantId);
stmt.setString(2, policyType);
resultSet = stmt.executeQuery();
return this.extractPolicyListFromDbResult(resultSet, tenantId);
} catch (SQLException e) {
String msg = "Error occurred while reading the policies from the database ";
log.error(msg, e);
throw new PolicyManagerDAOException(msg, e);
} finally {
PolicyManagementDAOUtil.cleanupResources(stmt, resultSet);
}
}
private List<Policy> extractPolicyListFromDbResult(ResultSet resultSet, int tenantId) throws SQLException {
List<Policy> policies = new ArrayList<>();
while (resultSet.next()) {
Policy policy = new Policy();
policy.setId(resultSet.getInt("ID"));
policy.setProfileId(resultSet.getInt("PROFILE_ID"));
policy.setPolicyName(resultSet.getString("NAME"));
policy.setTenantId(tenantId);
policy.setPriorityId(resultSet.getInt("PRIORITY"));
policy.setCompliance(resultSet.getString("COMPLIANCE"));
policy.setOwnershipType(resultSet.getString("OWNERSHIP_TYPE"));
policy.setUpdated(PolicyManagerUtil.convertIntToBoolean(resultSet.getInt("UPDATED")));
policy.setActive(PolicyManagerUtil.convertIntToBoolean(resultSet.getInt("ACTIVE")));
policy.setDescription(resultSet.getString("DESCRIPTION"));
policy.setPolicyType(resultSet.getString("POLICY_TYPE"));
policies.add(policy);
}
return policies;
}
} }

@ -377,4 +377,12 @@ public class PolicyAdministratorPointImpl implements PolicyAdministratorPoint {
} }
} }
@Override
public List<Policy> getPolicies(String policyType) throws PolicyManagementException {
if (policyConfiguration.getCacheEnable()) {
return PolicyCacheManagerImpl.getInstance().getAllPolicies(policyType);
} else {
return policyManager.getPolicies(policyType);
}
}
} }

@ -83,4 +83,6 @@ public interface PolicyManager {
Policy getAppliedPolicyToDevice(DeviceIdentifier deviceIdentifier) throws PolicyManagementException; Policy getAppliedPolicyToDevice(DeviceIdentifier deviceIdentifier) throws PolicyManagementException;
HashMap<Integer, Integer> getAppliedPolicyIdsDeviceIds() throws PolicyManagementException; HashMap<Integer, Integer> getAppliedPolicyIdsDeviceIds() throws PolicyManagementException;
List<Policy> getPolicies(String type) throws PolicyManagementException;
} }

@ -626,25 +626,7 @@ public class PolicyManagerImpl implements PolicyManager {
try { try {
PolicyManagementDAOFactory.openConnection(); PolicyManagementDAOFactory.openConnection();
policyList = policyDAO.getAllPolicies(); policyList = policyDAO.getAllPolicies();
this.buildPolicyList(policyList, profileList);
for (Policy policy : policyList) {
for (Profile profile : profileList) {
if (policy.getProfileId() == profile.getProfileId()) {
policy.setProfile(profile);
}
}
policy.setRoles(policyDAO.getPolicyAppliedRoles(policy.getId()));
policy.setUsers(policyDAO.getPolicyAppliedUsers(policy.getId()));
policy.setPolicyCriterias(policyDAO.getPolicyCriteria(policy.getId()));
List<DeviceGroupWrapper> deviceGroupWrappers = policyDAO.getDeviceGroupsOfPolicy(policy.getId());
if (!deviceGroupWrappers.isEmpty()) {
deviceGroupWrappers = this.getDeviceGroupNames(deviceGroupWrappers);
}
policy.setDeviceGroups(deviceGroupWrappers);
}
Collections.sort(policyList);
} catch (PolicyManagerDAOException e) { } catch (PolicyManagerDAOException e) {
throw new PolicyManagementException("Error occurred while getting all the policies.", e); throw new PolicyManagementException("Error occurred while getting all the policies.", e);
} catch (SQLException e) { } catch (SQLException e) {
@ -1144,4 +1126,60 @@ public class PolicyManagerImpl implements PolicyManager {
return policyRevokeOperation; return policyRevokeOperation;
} }
@Override
public List<Policy> getPolicies(String type) throws PolicyManagementException {
List<Policy> policyList;
List<Profile> profileList;
try {
profileList = profileManager.getAllProfiles();
} catch (ProfileManagementException e) {
throw new PolicyManagementException("Error occurred while getting all the profiles.", e);
}
try {
PolicyManagementDAOFactory.openConnection();
policyList = policyDAO.getAllPolicies(type);
this.buildPolicyList(policyList, profileList);
} catch (PolicyManagerDAOException e) {
String msg = "Error occurred while getting all the policies. ";
log.error(msg, e);
throw new PolicyManagementException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while opening a connection to the data source ";
log.error(msg, e);
throw new PolicyManagementException(msg, e);
} catch (GroupManagementException e) {
String msg = "Error occurred while getting device groups. ";
log.error(msg, e);
throw new PolicyManagementException(msg, e);
} finally {
PolicyManagementDAOFactory.closeConnection();
}
for (Policy policy : policyList) {
policy.setDevices(this.getPolicyAppliedDevicesIds(policy.getId()));
}
return policyList;
}
private void buildPolicyList(List<Policy> policyList, List<Profile> profileList)
throws PolicyManagerDAOException, GroupManagementException {
for (Policy policy : policyList) {
for (Profile profile : profileList) {
if (policy.getProfileId() == profile.getProfileId()) {
policy.setProfile(profile);
}
}
policy.setRoles(policyDAO.getPolicyAppliedRoles(policy.getId()));
policy.setUsers(policyDAO.getPolicyAppliedUsers(policy.getId()));
policy.setPolicyCriterias(policyDAO.getPolicyCriteria(policy.getId()));
List<DeviceGroupWrapper> deviceGroupWrappers = policyDAO.getDeviceGroupsOfPolicy(policy.getId());
if (!deviceGroupWrappers.isEmpty()) {
deviceGroupWrappers = this.getDeviceGroupNames(deviceGroupWrappers);
}
policy.setDeviceGroups(deviceGroupWrappers);
}
Collections.sort(policyList);
}
} }

@ -132,6 +132,7 @@ public class PolicyManagerServiceImplTest extends BasePolicyManagementDAOTest {
policy1.setDeviceGroups(deviceGroupWrappers); policy1.setDeviceGroups(deviceGroupWrappers);
List<Device> devices = new ArrayList<Device>(); List<Device> devices = new ArrayList<Device>();
policy1.setDevices(devices); policy1.setDevices(devices);
policy1.setPolicyType("GENERAL");
policy1.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()); policy1.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
policy1 = policyManagerService.addPolicy(policy1); policy1 = policyManagerService.addPolicy(policy1);

@ -40,6 +40,7 @@ public class PolicyCreator {
policy.setCompliance("NOTIFY"); policy.setCompliance("NOTIFY");
policy.setOwnershipType("COPE"); policy.setOwnershipType("COPE");
policy.setDescription("This is the first policy."); policy.setDescription("This is the first policy.");
policy.setPolicyType("GENERAL");
return policy; return policy;
} }
@ -51,6 +52,7 @@ public class PolicyCreator {
policy.setPolicyName("Test_Policy_02"); policy.setPolicyName("Test_Policy_02");
policy.setGeneric(true); policy.setGeneric(true);
policy.setProfile(profile); policy.setProfile(profile);
policy.setPolicyType("GENERAL");
policy.setDevices(DeviceCreator.getDeviceList2(DeviceTypeCreator.getDeviceType())); policy.setDevices(DeviceCreator.getDeviceList2(DeviceTypeCreator.getDeviceType()));
policy.setCompliance("ENFORCE"); policy.setCompliance("ENFORCE");
@ -110,7 +112,7 @@ public class PolicyCreator {
policy.setRoles(roles); policy.setRoles(roles);
policy.setCompliance("ENFORCE"); policy.setCompliance("ENFORCE");
policy.setOwnershipType("BYOD"); policy.setOwnershipType("BYOD");
policy.setPolicyType("GENERAL");
PolicyCriterion criterion = new PolicyCriterion(); PolicyCriterion criterion = new PolicyCriterion();
@ -144,7 +146,7 @@ public class PolicyCreator {
policy.setCompliance("MONITOR"); policy.setCompliance("MONITOR");
policy.setOwnershipType("BYOD"); policy.setOwnershipType("BYOD");
policy.setPolicyType("GENERAL");
List<String> roles = new ArrayList<String>(); List<String> roles = new ArrayList<String>();
roles.add("Role_04"); roles.add("Role_04");
roles.add("Role_05"); roles.add("Role_05");

@ -200,6 +200,7 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
PRIORITY INT NOT NULL, PRIORITY INT NOT NULL,
ACTIVE INT(2) NOT NULL, ACTIVE INT(2) NOT NULL,
UPDATED INT(1) NULL, UPDATED INT(1) NULL,
POLICY_TYPE VARCHAR(45) NULL,
PRIMARY KEY (ID) , PRIMARY KEY (ID) ,
CONSTRAINT FK_DM_PROFILE_DM_POLICY CONSTRAINT FK_DM_PROFILE_DM_POLICY
FOREIGN KEY (PROFILE_ID ) FOREIGN KEY (PROFILE_ID )

@ -193,6 +193,7 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
PRIORITY INT NOT NULL, PRIORITY INT NOT NULL,
ACTIVE INT(2) NOT NULL, ACTIVE INT(2) NOT NULL,
UPDATED INT(1) NULL, UPDATED INT(1) NULL,
POLICY_TYPE VARCHAR(45) NULL,
PRIMARY KEY (ID) , PRIMARY KEY (ID) ,
CONSTRAINT FK_DM_PROFILE_DM_POLICY CONSTRAINT FK_DM_PROFILE_DM_POLICY
FOREIGN KEY (PROFILE_ID ) FOREIGN KEY (PROFILE_ID )

@ -246,6 +246,7 @@ CREATE TABLE DM_POLICY (
PRIORITY INTEGER NOT NULL, PRIORITY INTEGER NOT NULL,
ACTIVE BIT NOT NULL DEFAULT 0, ACTIVE BIT NOT NULL DEFAULT 0,
UPDATED BIT NULL DEFAULT 0, UPDATED BIT NULL DEFAULT 0,
POLICY_TYPE VARCHAR(45) NULL,
PRIMARY KEY (ID) , PRIMARY KEY (ID) ,
CONSTRAINT FK_DM_PROFILE_DM_POLICY FOREIGN KEY (PROFILE_ID) REFERENCES DM_PROFILE (ID) CONSTRAINT FK_DM_PROFILE_DM_POLICY FOREIGN KEY (PROFILE_ID) REFERENCES DM_PROFILE (ID)
ON DELETE NO ACTION ON UPDATE NO ACTION ON DELETE NO ACTION ON UPDATE NO ACTION

@ -224,6 +224,7 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
PRIORITY INT NOT NULL, PRIORITY INT NOT NULL,
ACTIVE INT(2) NOT NULL, ACTIVE INT(2) NOT NULL,
UPDATED INT(1) NULL, UPDATED INT(1) NULL,
POLICY_TYPE VARCHAR(45) NULL,
PRIMARY KEY (ID) , PRIMARY KEY (ID) ,
CONSTRAINT FK_DM_PROFILE_DM_POLICY CONSTRAINT FK_DM_PROFILE_DM_POLICY
FOREIGN KEY (PROFILE_ID ) FOREIGN KEY (PROFILE_ID )

@ -357,6 +357,7 @@ CREATE TABLE DM_POLICY (
PRIORITY NUMBER(10) NOT NULL, PRIORITY NUMBER(10) NOT NULL,
ACTIVE NUMBER(10) NOT NULL, ACTIVE NUMBER(10) NOT NULL,
UPDATED NUMBER(10) NULL, UPDATED NUMBER(10) NULL,
POLICY_TYPE VARCHAR2(45) NULL,
CONSTRAINT PK_DM_PROFILE_DM_POLICY PRIMARY KEY (ID) , CONSTRAINT PK_DM_PROFILE_DM_POLICY PRIMARY KEY (ID) ,
CONSTRAINT FK_DM_PROFILE_DM_POLICY CONSTRAINT FK_DM_PROFILE_DM_POLICY
FOREIGN KEY (PROFILE_ID ) FOREIGN KEY (PROFILE_ID )

@ -194,6 +194,7 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
PRIORITY INTEGER NOT NULL, PRIORITY INTEGER NOT NULL,
ACTIVE INTEGER NOT NULL, ACTIVE INTEGER NOT NULL,
UPDATED INTEGER NULL, UPDATED INTEGER NULL,
POLICY_TYPE VARCHAR(45) NULL,
CONSTRAINT FK_DM_PROFILE_DM_POLICY CONSTRAINT FK_DM_PROFILE_DM_POLICY
FOREIGN KEY (PROFILE_ID ) FOREIGN KEY (PROFILE_ID )
REFERENCES DM_PROFILE (ID ) REFERENCES DM_PROFILE (ID )

Loading…
Cancel
Save