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

Add a new API endpoint to get app subscription details.

See merge request entgra/carbon-device-mgt!340
feature/appm-store/pbac
Inosh Perara 5 years ago
commit d1af3d7ed1

@ -0,0 +1,80 @@
/* 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.application.mgt.common;
import org.wso2.carbon.device.mgt.common.Device;
import java.sql.Timestamp;
public class DeviceSubscriptionData {
private String action;
private Timestamp actionTriggeredTimestamp;
private String actionTriggeredBy;
private String actionType;
private String status;
private Device device;
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Timestamp getActionTriggeredTimestamp() {
return actionTriggeredTimestamp;
}
public void setActionTriggeredTimestamp(Timestamp actionTriggeredTimestamp) {
this.actionTriggeredTimestamp = actionTriggeredTimestamp;
}
public String getActionTriggeredBy() {
return actionTriggeredBy;
}
public void setActionTriggeredBy(String actionTriggeredBy) {
this.actionTriggeredBy = actionTriggeredBy;
}
public String getActionType() {
return actionType;
}
public void setActionType(String actionType) {
this.actionType = actionType;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
}

@ -108,4 +108,18 @@ public interface SubscriptionManager {
*/ */
PaginationResult getAppInstalledCategories(int offsetValue, int limitValue, String appUUID, PaginationResult getAppInstalledCategories(int offsetValue, int limitValue, String appUUID,
String subType) throws ApplicationManagementException; String subType) throws ApplicationManagementException;
/**
* This method is responsible to provide application subscription data for given application release UUID.
*
* @param offsetValue offset
* @param limitValue limit
* @param appUUID application release UUID
* @return {@link PaginationResult}
* @throws ApplicationManagementException if offset or limit contains incorrect values, if it couldn't find an
* application release for given UUID, if an error occurred while getting device details of subscribed device ids,
* if an error occurred while getting subscription details of given application release UUID.
*/
PaginationResult getAppSubscriptionDetails(int offsetValue, int limitValue, String appUUID)
throws ApplicationManagementException;
} }

@ -30,6 +30,7 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse;
import org.wso2.carbon.device.application.mgt.common.ApplicationType; import org.wso2.carbon.device.application.mgt.common.ApplicationType;
import org.wso2.carbon.device.application.mgt.common.DeviceSubscriptionData;
import org.wso2.carbon.device.application.mgt.common.DeviceTypes; import org.wso2.carbon.device.application.mgt.common.DeviceTypes;
import org.wso2.carbon.device.application.mgt.common.ExecutionStatus; import org.wso2.carbon.device.application.mgt.common.ExecutionStatus;
import org.wso2.carbon.device.application.mgt.common.SubAction; import org.wso2.carbon.device.application.mgt.common.SubAction;
@ -315,6 +316,15 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} }
/**
* THis method is responsible to validate application install or uninstall request.
*
* @param params params could be either list of {@link DeviceIdentifier} or list of username or list of group
* names or list or role names.
* @param subType Subscription type. i.e DEVICE or USER or ROLE or GROUP
* @param action performing action. i.e Install or Uninstall
* @throws BadRequestException if incompatible data is found with app install/uninstall request.
*/
private <T> void validateRequest(List<T> params, String subType, String action) throws BadRequestException { private <T> void validateRequest(List<T> params, String subType, String action) throws BadRequestException {
if (params.isEmpty()) { if (params.isEmpty()) {
String msg = "In order to install application release, you should provide list of subscribers. " String msg = "In order to install application release, you should provide list of subscribers. "
@ -338,7 +348,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} }
/*** /**
* This method perform given action (i.e APP INSTALL or APP UNINSTALL) on given set of devices. * This method perform given action (i.e APP INSTALL or APP UNINSTALL) on given set of devices.
* *
* @param deviceType Application supported device type. * @param deviceType Application supported device type.
@ -424,7 +434,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return applicationInstallResponse; return applicationInstallResponse;
} }
/*** /**
* Filter given devices and davide given list of device into two sets, those are already application installed * Filter given devices and davide given list of device into two sets, those are already application installed
* devices and application installable devices. * devices and application installable devices.
* *
@ -469,6 +479,13 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return subscribingDeviceIdHolder; return subscribingDeviceIdHolder;
} }
/**
* This method returns the application categories of a particular application
*
* @param id Application Id
* @return List of application categories.
* @throws ApplicationManagementException if error occurred while getting application categories from the DB.
*/
private List<String> getApplicationCategories(int id) throws ApplicationManagementException { private List<String> getApplicationCategories(int id) throws ApplicationManagementException {
List<String> categories; List<String> categories;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
@ -528,6 +545,18 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} }
/**
* This method is responsible to update subscription data.
*
* @param applicationReleaseId Application release Id
* @param activities List of {@link Activity}
* @param subscribingDeviceIdHolder Subscribing device id holder.
* @param params subscribers. If subscription is performed via user, group or role, params is a list of
* {@link String}
* @param subType Subscription type. i.e USER, GROUP, ROLE or DEVICE
* @param action performing action. ie INSTALL or UNINSTALL>
* @throws ApplicationManagementException if error occurred while getting or updating subscription data.
*/
private void updateSubscriptions(int applicationReleaseId, List<Activity> activities, private void updateSubscriptions(int applicationReleaseId, List<Activity> activities,
SubscribingDeviceIdHolder subscribingDeviceIdHolder, List<String> params, String subType, SubscribingDeviceIdHolder subscribingDeviceIdHolder, List<String> params, String subType,
String action) throws ApplicationManagementException { String action) throws ApplicationManagementException {
@ -685,6 +714,16 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} }
/**
* This method constructs operation payload to install/uninstall an application.
*
* @param deviceType Device type
* @param application {@link Application} data.
* @param action Action is either ININSTALL or UNINSTALL
* @return {@link Operation}
* @throws ApplicationManagementException if unknown application type is found to generate operation payload or
* invalid action is found to generate operation payload.
*/
private Operation generateOperationPayloadByDeviceType(String deviceType, Application application, String action) private Operation generateOperationPayloadByDeviceType(String deviceType, Application application, String action)
throws ApplicationManagementException { throws ApplicationManagementException {
try { try {
@ -865,7 +904,6 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} }
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred when get application release data for application" + String msg = "Error occurred when get application release data for application" +
" release UUID: " + appUUID; " release UUID: " + appUUID;
log.error(msg, e); log.error(msg, e);
@ -881,8 +919,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public PaginationResult getAppInstalledCategories(int offsetValue, int limitValue, public PaginationResult getAppInstalledCategories(int offsetValue, int limitValue, String appUUID, String subType)
String appUUID, String subType)
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
@ -893,28 +930,24 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
.getAppWithRelatedRelease(appUUID, tenantId); .getAppWithRelatedRelease(appUUID, tenantId);
int applicationReleaseId = applicationDTO.getApplicationReleaseDTOs().get(0).getId(); int applicationReleaseId = applicationDTO.getApplicationReleaseDTOs().get(0).getId();
int count = 0; List<String> subscriptionList = new ArrayList<>();
List<String> SubscriptionList = new ArrayList<>();
if (SubscriptionType.USER.toString().equalsIgnoreCase(subType)) { if (SubscriptionType.USER.toString().equalsIgnoreCase(subType)) {
SubscriptionList = subscriptionDAO subscriptionList = subscriptionDAO
.getAppSubscribedUsers(offsetValue, limitValue, applicationReleaseId, tenantId); .getAppSubscribedUsers(offsetValue, limitValue, applicationReleaseId, tenantId);
} else if (SubscriptionType.ROLE.toString().equalsIgnoreCase(subType)) { } else if (SubscriptionType.ROLE.toString().equalsIgnoreCase(subType)) {
SubscriptionList = subscriptionDAO subscriptionList = subscriptionDAO
.getAppSubscribedRoles(offsetValue, limitValue, applicationReleaseId, tenantId); .getAppSubscribedRoles(offsetValue, limitValue, applicationReleaseId, tenantId);
} else if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) { } else if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) {
SubscriptionList = subscriptionDAO subscriptionList = subscriptionDAO
.getAppSubscribedGroups(offsetValue, limitValue, applicationReleaseId, tenantId); .getAppSubscribedGroups(offsetValue, limitValue, applicationReleaseId, tenantId);
} }
count = SubscriptionList.size(); int count = subscriptionList.size();
paginationResult.setData(SubscriptionList); paginationResult.setData(subscriptionList);
paginationResult.setRecordsFiltered(count); paginationResult.setRecordsFiltered(count);
paginationResult.setRecordsTotal(count); paginationResult.setRecordsTotal(count);
return paginationResult; return paginationResult;
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred when get application release data for application" + String msg = "Error occurred when get application release data for application" +
" release UUID: " + appUUID; " release UUID: " + appUUID;
log.error(msg, e); log.error(msg, e);
@ -928,4 +961,97 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.closeDBConnection();
} }
} }
@Override
public PaginationResult getAppSubscriptionDetails(int offsetValue, int limitValue, String appUUID)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
DeviceManagementProviderService deviceManagementProviderService = HelperUtil
.getDeviceManagementProviderService();
if (offsetValue < 0 || limitValue <= 0) {
String msg = "Found incompatible values for offset and limit. Hence please check the request and resend. "
+ "Offset " + offsetValue + " limit " + limitValue;
log.error(msg);
throw new BadRequestException(msg);
}
try {
ConnectionManagerUtil.openDBConnection();
ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(appUUID, tenantId);
if (applicationDTO == null) {
String msg = "Couldn't find an application with application release which has UUID " + appUUID;
log.error(msg);
throw new NotFoundException(msg);
}
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 = deviceSubscriptionDTOS.stream().map(DeviceSubscriptionDTO::getDeviceId)
.collect(Collectors.toList());
if (deviceIdList.isEmpty()) {
PaginationResult paginationResult = new PaginationResult();
paginationResult.setData(deviceIdList);
paginationResult.setRecordsFiltered(0);
paginationResult.setRecordsTotal(0);
return paginationResult;
}
try {
//pass the device id list to device manager service method
PaginationResult paginationResult = deviceManagementProviderService
.getAppSubscribedDevices(offsetValue, limitValue, deviceIdList, null);
List<DeviceSubscriptionData> deviceSubscriptionDataList = new ArrayList<>();
if (!paginationResult.getData().isEmpty()) {
List<Device> devices = (List<Device>) paginationResult.getData();
for (Device device : devices) {
DeviceSubscriptionData deviceSubscriptionData = new DeviceSubscriptionData();
for (DeviceSubscriptionDTO subscription : deviceSubscriptionDTOS) {
if (subscription.getDeviceId() == device.getId()) {
deviceSubscriptionData.setDevice(device);
if (subscription.isUnsubscribed()) {
deviceSubscriptionData.setAction(Constants.UNSUBSCRIBED);
deviceSubscriptionData.setActionTriggeredBy(subscription.getUnsubscribedBy());
deviceSubscriptionData
.setActionTriggeredTimestamp(subscription.getUnsubscribedTimestamp());
} else {
deviceSubscriptionData.setAction(Constants.SUBSCRIBED);
deviceSubscriptionData.setActionTriggeredBy(subscription.getSubscribedBy());
deviceSubscriptionData
.setActionTriggeredTimestamp(subscription.getSubscribedTimestamp());
}
deviceSubscriptionData.setActionType(subscription.getActionTriggeredFrom());
deviceSubscriptionData.setStatus(subscription.getStatus());
deviceSubscriptionDataList.add(deviceSubscriptionData);
break;
}
}
}
}
paginationResult.setData(deviceSubscriptionDataList);
return paginationResult;
} catch (DeviceManagementException e) {
String msg = "service error occurred while getting device data from the device management service. "
+ "Device ids " + deviceIdList;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
} catch (ApplicationManagementDAOException e) {
String msg = "Error occurred when getting 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 trying to get subscription data of application which has "
+ "application release UUID " + appUUID;
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
} }

@ -58,6 +58,9 @@ public class Constants {
public static final String TENANT_DOMAIN = "TENANT_DOMAIN"; public static final String TENANT_DOMAIN = "TENANT_DOMAIN";
public static final String TENANT_ID = "__TENANT_ID_PROP__"; public static final String TENANT_ID = "__TENANT_ID_PROP__";
public static final String TASK_NAME = "TASK_NAME"; public static final String TASK_NAME = "TASK_NAME";
public static final String SUBSCRIBED = "SUBSCRIBED";
public static final String UNSUBSCRIBED = "UNSUBSCRIBED";
/** /**
* Database types supported by Application Management. * Database types supported by Application Management.

@ -49,7 +49,7 @@ info = @Info(
extensions = { extensions = {
@Extension(properties = { @Extension(properties = {
@ExtensionProperty(name = "name", value = "StoreReviewManagementAdminService"), @ExtensionProperty(name = "name", value = "StoreReviewManagementAdminService"),
@ExtensionProperty(name = "context", value = "/api/application-mgt-store/v1.0/admin/review"), @ExtensionProperty(name = "context", value = "/api/application-mgt-store/v1.0/admin/reviews"),
}) })
} }
), ),
@ -70,14 +70,13 @@ scopes = {
@Path("/admin/reviews") @Path("/admin/reviews")
@Api(value = "Store Review Management Admin API") @Api(value = "Store Review Management Admin API")
@Produces(MediaType.APPLICATION_JSON)
public interface ReviewManagementStoreAdminAPI { public interface ReviewManagementStoreAdminAPI {
String SCOPE = "scope"; String SCOPE = "scope";
@DELETE @DELETE
@Path("/{uuid}/{reviewId}") @Path("/{uuid}/{reviewId}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.WILDCARD)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.WILDCARD)
@ApiOperation( @ApiOperation(
consumes = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,

@ -0,0 +1,132 @@
/*
* 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.store.api.services.admin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
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 javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
/**
* API to handle subscription management related admin tasks.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "Subscription Management Admin Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "SubscriptionManagementAdminService"),
@ExtensionProperty(name = "context", value = "/api/application-mgt-store/v1.0/admin/subscription"),
})
}
),
tags = {
@Tag(name = "subscription_management, device_management", description = "Subscription Management "
+ "related Admin APIs")
}
)
@Scopes(
scopes = {
@org.wso2.carbon.apimgt.annotations.api.Scope(
name = "View Application Subscriptions",
description = "View Application Subscriptions.",
key = "perm:admin:app:subscription:view",
permissions = {"/app-mgt/store/admin/subscription/view"}
)
}
)
@Path("/admin/subscription")
@Api(value = "Subscription Management Admin API")
@Produces(MediaType.APPLICATION_JSON)
public interface SubscriptionManagementAdminAPI {
String SCOPE = "scope";
@GET
@Path("/{uuid}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get subscription details of specific application.",
notes = "This will get the subscription details of specific application",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved subscription 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 = 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
);
}

@ -18,9 +18,6 @@ package org.wso2.carbon.device.application.mgt.store.api.services.impl.admin;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.common.PaginationRequest;
import org.wso2.carbon.device.application.mgt.common.PaginationResult;
import org.wso2.carbon.device.application.mgt.common.Rating;
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.ReviewManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ReviewManagementException;
import org.wso2.carbon.device.application.mgt.common.services.ReviewManager; import org.wso2.carbon.device.application.mgt.common.services.ReviewManager;
@ -28,9 +25,12 @@ import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException;
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.admin.ReviewManagementStoreAdminAPI; import org.wso2.carbon.device.application.mgt.store.api.services.admin.ReviewManagementStoreAdminAPI;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
/** /**
@ -44,6 +44,8 @@ public class ReviewManagementStoreAdminAPIImpl implements ReviewManagementStoreA
@Override @Override
@DELETE @DELETE
@Path("/{uuid}/{reviewId}") @Path("/{uuid}/{reviewId}")
@Produces(MediaType.WILDCARD)
@Consumes(MediaType.WILDCARD)
public Response deleteReview( public Response deleteReview(
@PathParam("uuid") String uuid, @PathParam("uuid") String uuid,
@PathParam("reviewId") int reviewId) { @PathParam("reviewId") int reviewId) {

@ -0,0 +1,81 @@
/*
* 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.application.mgt.store.api.services.impl.admin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.core.exception.BadRequestException;
import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.application.mgt.store.api.services.admin.SubscriptionManagementAdminAPI;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
/**
* Implementation of Subscription Management related APIs.
*/
@Produces({"application/json"})
@Path("/admin/subscription")
public class SubscriptionManagementAdminAPIImpl implements SubscriptionManagementAdminAPI {
private static Log log = LogFactory.getLog(SubscriptionManagementAdminAPIImpl.class);
@GET
@Consumes("application/json")
@Produces("application/json")
@Path("/{uuid}")
public Response getAppInstalledDevices(
@PathParam("uuid") String uuid,
@DefaultValue("0")
@QueryParam("offset") int offset,
@DefaultValue("5")
@QueryParam("limit") int limit) {
try {
SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager();
PaginationResult subscriptionData = subscriptionManager
.getAppSubscriptionDetails(offset, limit, uuid);
return Response.status(Response.Status.OK).entity(subscriptionData).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 (ApplicationManagementException e) {
String msg = "Error occurred while getting app installed devices which has application release UUID of: "
+ uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
}

@ -24,6 +24,7 @@
<jaxrs:server id="applicationMgtService" address="/"> <jaxrs:server id="applicationMgtService" address="/">
<jaxrs:serviceBeans> <jaxrs:serviceBeans>
<ref bean="subscriptionMgtAdminServiceBean"/>
<ref bean="reviewMgtAdminServiceBean"/> <ref bean="reviewMgtAdminServiceBean"/>
<ref bean="applicationMgtServiceBean"/> <ref bean="applicationMgtServiceBean"/>
<ref bean="reviewMgtServiceBean"/> <ref bean="reviewMgtServiceBean"/>
@ -55,6 +56,7 @@
<bean id="swaggerResource" class="io.swagger.jaxrs.listing.ApiListingResource" /> <bean id="swaggerResource" class="io.swagger.jaxrs.listing.ApiListingResource" />
<bean id="reviewMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.admin.ReviewManagementStoreAdminAPIImpl" /> <bean id="reviewMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.admin.ReviewManagementStoreAdminAPIImpl" />
<bean id="subscriptionMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.admin.SubscriptionManagementAdminAPIImpl" />
<bean id="applicationMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ApplicationManagementAPIImpl"/> <bean id="applicationMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ApplicationManagementAPIImpl"/>
<bean id="reviewMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ReviewManagementAPIImpl" /> <bean id="reviewMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ReviewManagementAPIImpl" />
<bean id="subscriptionMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.SubscriptionManagementAPIImpl"/> <bean id="subscriptionMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.SubscriptionManagementAPIImpl"/>

@ -576,8 +576,18 @@ public interface DeviceDAO {
* @param limitValue limit value for get paginated request. * @param limitValue limit value for get paginated request.
* @param status status of the devices. * @param status status of the devices.
* @return devices - subscribed device details list * @return devices - subscribed device details list
* @throws {@link DeviceManagementDAOException} if connections establishment fails. * @throws DeviceManagementDAOException if connections establishment fails.
*/ */
List<Device> getSubscribedDevices(int offsetValue, int limitValue, List<Integer> deviceIds, List<Device> getSubscribedDevices(int offsetValue, int limitValue, List<Integer> deviceIds,
int tenantId, String status) throws DeviceManagementDAOException; int tenantId, String status) throws DeviceManagementDAOException;
/**
* @param deviceIds device ids of the subscribed devices.
* @param tenantId tenant id
* @param status current status of the device. (e.g ACTIVE, REMOVED, etc)
* @return number of subscribed device count.
* @throws DeviceManagementDAOException if error occurred while processing the SQL statement.
*/
int getSubscribedDeviceCount(List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException;
} }

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl.device; package org.wso2.carbon.device.mgt.core.dao.impl.device;
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;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
@ -645,6 +646,52 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
} }
} }
@Override
public int getSubscribedDeviceCount(List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
try {
Connection conn = this.getConnection();
int index = 1;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"COUNT(e.DEVICE_ID) AS DEVICE_ID "+
"FROM DM_ENROLMENT AS e, DM_DEVICE AS f "+
"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 (!StringUtils.isBlank(status)) {
query = query + " AND e.STATUS = ?";
}
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (!StringUtils.isBlank(status)) {
ps.setString(index, status);
}
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return rs.getInt("DEVICE_ID");
}
return 0;
}
}
} 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();
} }

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl.device; package org.wso2.carbon.device.mgt.core.dao.impl.device;
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;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
@ -648,6 +649,52 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
} }
} }
@Override
public int getSubscribedDeviceCount(List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
try {
Connection conn = this.getConnection();
int index = 1;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"COUNT(e.DEVICE_ID) AS DEVICE_ID "+
"FROM DM_ENROLMENT AS e, DM_DEVICE AS f "+
"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 (!StringUtils.isBlank(status)) {
query = query + " AND e.STATUS = ?";
}
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (!StringUtils.isBlank(status)) {
ps.setString(index, status);
}
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return rs.getInt("DEVICE_ID");
}
return 0;
}
}
} 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();
} }

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl.device; package org.wso2.carbon.device.mgt.core.dao.impl.device;
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;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
@ -628,6 +629,52 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
} }
} }
@Override
public int getSubscribedDeviceCount(List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
try {
Connection conn = this.getConnection();
int index = 1;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"COUNT(e.DEVICE_ID) AS DEVICE_ID "+
"FROM DM_ENROLMENT AS e, DM_DEVICE AS f "+
"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 (!StringUtils.isBlank(status)) {
query = query + " AND e.STATUS = ?";
}
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (!StringUtils.isBlank(status)) {
ps.setString(index, status);
}
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return rs.getInt("DEVICE_ID");
}
return 0;
}
}
} 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();
} }

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.dao.impl.device; package org.wso2.carbon.device.mgt.core.dao.impl.device;
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;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
@ -650,4 +651,50 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
} }
return devices; return devices;
} }
@Override
public int getSubscribedDeviceCount(List<Integer> deviceIds, int tenantId, String status)
throws DeviceManagementDAOException {
try {
Connection conn = this.getConnection();
int index = 1;
StringJoiner joiner = new StringJoiner(",",
"SELECT " +
"COUNT(e.DEVICE_ID) AS DEVICE_ID "+
"FROM DM_ENROLMENT AS e, DM_DEVICE AS f "+
"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 (!StringUtils.isBlank(status)) {
query = query + " AND e.STATUS = ?";
}
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index++, tenantId);
if (!StringUtils.isBlank(status)) {
ps.setString(index, status);
}
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return rs.getInt("DEVICE_ID");
}
return 0;
}
}
} 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);
}
}
} }

@ -802,9 +802,8 @@ public interface DeviceManagementProviderService {
* @param limitValue limit value for get paginated request. * @param limitValue limit value for get paginated request.
* @param status status of the devices. * @param status status of the devices.
* @return {@link PaginationResult} * @return {@link PaginationResult}
* @throws {@link DeviceManagementException} if any service level or DAO level error occurs. * @throws DeviceManagementException if any service level or DAO level error occurs.
*/ */
PaginationResult getAppSubscribedDevices(int offsetValue, int limitValue, PaginationResult getAppSubscribedDevices(int offsetValue, int limitValue,
List<Integer> devicesIds, String status) List<Integer> devicesIds, String status) throws DeviceManagementException;
throws DeviceManagementException;
} }

@ -3702,31 +3702,9 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} }
} }
/**
* Wrap the device configuration data into DeviceConfiguration bean
* @param device Device queried using the properties
* @param tenantDomain tenant domain
* @param configurationEntries platformConfiguration list
* @param deviceOwner name of the device owner
* @return Wrapped {@link DeviceConfiguration} object with data
*/
private DeviceConfiguration wrapConfigurations(Device device,
String tenantDomain,
List<ConfigurationEntry> configurationEntries,
String deviceOwner) {
DeviceConfiguration deviceConfiguration = new DeviceConfiguration();
deviceConfiguration.setDeviceId(device.getDeviceIdentifier());
deviceConfiguration.setDeviceType(device.getType());
deviceConfiguration.setTenantDomain(tenantDomain);
deviceConfiguration.setConfigurationEntries(configurationEntries);
deviceConfiguration.setDeviceOwner(deviceOwner);
return deviceConfiguration;
}
@Override @Override
public PaginationResult getAppSubscribedDevices(int offsetValue, int limitValue, public PaginationResult getAppSubscribedDevices(int offsetValue, int limitValue, List<Integer> devicesIds,
List<Integer> devicesIds, String status) String status) throws DeviceManagementException {
throws DeviceManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -3739,8 +3717,16 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
DeviceManagementDAOFactory.openConnection(); DeviceManagementDAOFactory.openConnection();
subscribedDeviceDetails = deviceDAO subscribedDeviceDetails = deviceDAO
.getSubscribedDevices(offsetValue, limitValue, devicesIds, tenantId, status); .getSubscribedDevices(offsetValue, limitValue, devicesIds, tenantId, status);
count = subscribedDeviceDetails.size(); if (subscribedDeviceDetails.isEmpty()){
paginationResult.setData(new ArrayList<>());
paginationResult.setRecordsFiltered(0);
paginationResult.setRecordsTotal(0);
}
count = deviceDAO.getSubscribedDeviceCount(devicesIds, tenantId, status);
paginationResult.setData(getAllDeviceInfo(subscribedDeviceDetails));
paginationResult.setRecordsFiltered(count);
paginationResult.setRecordsTotal(count);
return paginationResult;
} catch (DeviceManagementDAOException e) { } catch (DeviceManagementDAOException e) {
String msg = "Error occurred while retrieving device list for device ids " + devicesIds; String msg = "Error occurred while retrieving device list for device ids " + devicesIds;
log.error(msg, e); log.error(msg, e);
@ -3752,9 +3738,26 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} finally { } finally {
DeviceManagementDAOFactory.closeConnection(); DeviceManagementDAOFactory.closeConnection();
} }
paginationResult.setData(getAllDeviceInfo(subscribedDeviceDetails)); }
paginationResult.setRecordsFiltered(count);
paginationResult.setRecordsTotal(count); /**
return paginationResult; * Wrap the device configuration data into DeviceConfiguration bean
* @param device Device queried using the properties
* @param tenantDomain tenant domain
* @param configurationEntries platformConfiguration list
* @param deviceOwner name of the device owner
* @return Wrapped {@link DeviceConfiguration} object with data
*/
private DeviceConfiguration wrapConfigurations(Device device,
String tenantDomain,
List<ConfigurationEntry> configurationEntries,
String deviceOwner) {
DeviceConfiguration deviceConfiguration = new DeviceConfiguration();
deviceConfiguration.setDeviceId(device.getDeviceIdentifier());
deviceConfiguration.setDeviceType(device.getType());
deviceConfiguration.setTenantDomain(tenantDomain);
deviceConfiguration.setConfigurationEntries(configurationEntries);
deviceConfiguration.setDeviceOwner(deviceOwner);
return deviceConfiguration;
} }
} }

@ -156,6 +156,7 @@
<Scope>perm:admin:app:review:view</Scope> <Scope>perm:admin:app:review:view</Scope>
<Scope>perm:admin:app:publisher:update</Scope> <Scope>perm:admin:app:publisher:update</Scope>
<Scope>perm:admin:app:review:update</Scope> <Scope>perm:admin:app:review:update</Scope>
<Scope>perm:admin:app:subscription:view</Scope>
<Scope>perm:device-types:types</Scope> <Scope>perm:device-types:types</Scope>
<Scope>perm:enterprise:modify</Scope> <Scope>perm:enterprise:modify</Scope>
<Scope>perm:enterprise:view</Scope> <Scope>perm:enterprise:view</Scope>
@ -255,7 +256,7 @@
<Scope>perm:device:enroll</Scope> <Scope>perm:device:enroll</Scope>
<Scope>perm:geo-service:analytics-view</Scope> <Scope>perm:geo-service:analytics-view</Scope>
<Scope>perm:geo-service:alerts-manage</Scope> <Scope>perm:geo-service:alerts-manage</Scope>
<Scope>appm:rea</Scope> <Scope>appm:read</Scope>
<Scope>perm:devices:permanent-delete</Scope> <Scope>perm:devices:permanent-delete</Scope>
</Scopes> </Scopes>
<SSOConfiguration> <SSOConfiguration>

Loading…
Cancel
Save