Add APIs for subscription management

feature/appm-store/pbac
lasanthaDLPDS 6 years ago
parent bd80f5d442
commit 7c593d83fa

@ -26,18 +26,19 @@ import java.util.List;
public class ApplicationInstallResponse {
@ApiModelProperty(
name = "successfulDevices",
name = "installedDevices",
value = "List of successful devices",
dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]"
)
private List<DeviceIdentifier> successfulDevices;
private List<DeviceIdentifier> installedDevices;
@ApiModelProperty(
name = "failedDevices",
value = "List of failed devices",
name = "alreadyInstalledDevices",
value = "List of devices that application release is already installed.",
dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]"
)
private List<DeviceIdentifier> failedDevices;
private List<DeviceIdentifier> alreadyInstalledDevices;
@ApiModelProperty(
name = "activity",
@ -45,20 +46,12 @@ public class ApplicationInstallResponse {
)
private Activity activity;
public List<DeviceIdentifier> getSuccessfulDevices() {
return successfulDevices;
}
public void setSuccessfulDevices(List<DeviceIdentifier> successfulDevices) {
this.successfulDevices = successfulDevices;
}
public List<DeviceIdentifier> getFailedDevices() {
return failedDevices;
public List<DeviceIdentifier> getInstalledDevices() {
return installedDevices;
}
public void setFailedDevices(List<DeviceIdentifier> failedDevices) {
this.failedDevices = failedDevices;
public void setInstalledDevices(List<DeviceIdentifier> installedDevices) {
this.installedDevices = installedDevices;
}
public Activity getActivity() {
@ -68,4 +61,12 @@ public class ApplicationInstallResponse {
public void setActivity(Activity activity) {
this.activity = activity;
}
public List<DeviceIdentifier> getAlreadyInstalledDevices() {
return alreadyInstalledDevices;
}
public void setAlreadyInstalledDevices(List<DeviceIdentifier> alreadyInstalledDevices) {
this.alreadyInstalledDevices = alreadyInstalledDevices;
}
}

@ -0,0 +1,71 @@
/*
* Copyright (c) 2018, 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.
*/
package org.wso2.carbon.device.application.mgt.common;
import io.swagger.annotations.ApiModelProperty;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import java.util.List;
public class ApplicationInstallResponseTmp {
@ApiModelProperty(
name = "successfulDevices",
value = "List of successful devices",
dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]"
)
private List<DeviceIdentifier> successfulDevices;
@ApiModelProperty(
name = "failedDevices",
value = "List of failed devices",
dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]"
)
private List<DeviceIdentifier> failedDevices;
@ApiModelProperty(
name = "activity",
value = "Activity corresponding to the operation"
)
private Activity activity;
public List<DeviceIdentifier> getSuccessfulDevices() {
return successfulDevices;
}
public void setSuccessfulDevices(List<DeviceIdentifier> successfulDevices) {
this.successfulDevices = successfulDevices;
}
public List<DeviceIdentifier> getFailedDevices() {
return failedDevices;
}
public void setFailedDevices(List<DeviceIdentifier> failedDevices) {
this.failedDevices = failedDevices;
}
public Activity getActivity() {
return activity;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
}

@ -0,0 +1,22 @@
/* 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;
public enum SubsciptionType {
USER, ROLE, DEVICE_GROUP
}

@ -26,8 +26,9 @@ public class DeviceSubscriptionDTO {
private Timestamp subscribedTimestamp;
private boolean isUnsubscribed;
private String unsubscribedBy;
private Timestamp unsubscribedTimestapm;
private Timestamp unsubscribedTimestamp;
private String subscribedFrom;
private String status;
private int deviceId;
public int getId() { return id; }
@ -52,16 +53,20 @@ public class DeviceSubscriptionDTO {
public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; }
public Timestamp getUnsubscribedTimestapm() { return unsubscribedTimestapm; }
public Timestamp getUnsubscribedTimestamp() { return unsubscribedTimestamp; }
public void setUnsubscribedTimestapm(Timestamp unsubscribedTimestapm) {
this.unsubscribedTimestapm = unsubscribedTimestapm;
public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) {
this.unsubscribedTimestamp = unsubscribedTimestamp;
}
public String getSubscribedFrom() { return subscribedFrom; }
public void setSubscribedFrom(String subscribedFrom) { this.subscribedFrom = subscribedFrom; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public int getDeviceId() { return deviceId; }
public void setDeviceId(int deviceId) { this.deviceId = deviceId; }

@ -0,0 +1,63 @@
/* 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.dto;
import java.sql.Timestamp;
public class GroupSubscriptionDTO {
private int id;
private String subscribedBy;
private Timestamp subscribedTimestamp;
private boolean isUnsubscribed;
private String unsubscribedBy;
private Timestamp unsubscribedTimestamp;
private String subscribedFrom;
private int groupdId;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getSubscribedBy() { return subscribedBy; }
public void setSubscribedBy(String subscribedBy) { this.subscribedBy = subscribedBy; }
public Timestamp getSubscribedTimestamp() { return subscribedTimestamp; }
public void setSubscribedTimestamp(Timestamp subscribedTimestamp) { this.subscribedTimestamp = subscribedTimestamp; }
public boolean isUnsubscribed() { return isUnsubscribed; }
public void setUnsubscribed(boolean unsubscribed) { isUnsubscribed = unsubscribed; }
public String getUnsubscribedBy() { return unsubscribedBy; }
public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; }
public Timestamp getUnsubscribedTimestamp() { return unsubscribedTimestamp; }
public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) { this.unsubscribedTimestamp = unsubscribedTimestamp; }
public String getSubscribedFrom() { return subscribedFrom; }
public void setSubscribedFrom(String subscribedFrom) { this.subscribedFrom = subscribedFrom; }
public int getGroupdId() { return groupdId; }
public void setGroupdId(int groupdId) { this.groupdId = groupdId; }
}

@ -0,0 +1,67 @@
/* 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.dto;
import java.sql.Timestamp;
public class RoleSubscriptionDTO {
private int id;
private String subscribedBy;
private Timestamp subscribedTimestamp;
private boolean isUnsubscribed;
private String unsubscribedBy;
private Timestamp unsubscribedTimestamp;
private String subscribedFrom;
private String roleName;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getSubscribedBy() { return subscribedBy; }
public void setSubscribedBy(String subscribedBy) { this.subscribedBy = subscribedBy; }
public Timestamp getSubscribedTimestamp() { return subscribedTimestamp; }
public void setSubscribedTimestamp(Timestamp subscribedTimestamp) {
this.subscribedTimestamp = subscribedTimestamp;
}
public boolean isUnsubscribed() { return isUnsubscribed; }
public void setUnsubscribed(boolean unsubscribed) { isUnsubscribed = unsubscribed; }
public String getUnsubscribedBy() { return unsubscribedBy; }
public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; }
public Timestamp getUnsubscribedTimestamp() { return unsubscribedTimestamp; }
public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) {
this.unsubscribedTimestamp = unsubscribedTimestamp;
}
public String getSubscribedFrom() { return subscribedFrom; }
public void setSubscribedFrom(String subscribedFrom) { this.subscribedFrom = subscribedFrom; }
public String getRoleName() { return roleName; }
public void setRoleName(String roleName) { this.roleName = roleName; }
}

@ -0,0 +1,31 @@
/* 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.dto;
import java.sql.Timestamp;
public class UserSubscriptionDTO {
private int id;
private String subscribedBy;
private Timestamp subscribedTimestamp;
private boolean isUnsubscribed;
private String unsubscribedBy;
private Timestamp unsubscribedTimestamp;
private String subscribedFrom;
private String userName;
}

@ -21,6 +21,8 @@ package org.wso2.carbon.device.application.mgt.common.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
@ApiModel(value = "ApplicationReleaseDTO", description = "This class holds the details when releasing an ApplicationDTO to application store")
public class ApplicationRelease {
@ -48,17 +50,9 @@ public class ApplicationRelease {
value = "icon file storing location")
private String iconPath;
@ApiModelProperty(name = "screenshotPath1",
value = "Screenshot storing location")
private String screenshotPath1;
@ApiModelProperty(name = "screenshotPath2",
@ApiModelProperty(name = "screenshots",
value = "Screenshot storing location")
private String screenshotPath2;
@ApiModelProperty(name = "screenshotPath3",
value = "Screenshot storing location")
private String screenshotPath3;
private List<String> screenshots;
@ApiModelProperty(name = "releaseType",
value = "Release type of the application release",
@ -163,18 +157,6 @@ public class ApplicationRelease {
public void setIconPath(String iconPath) { this.iconPath = iconPath; }
public String getScreenshotPath1() { return screenshotPath1; }
public void setScreenshotPath1(String screenshotPath1) { this.screenshotPath1 = screenshotPath1; }
public String getScreenshotPath2() { return screenshotPath2; }
public void setScreenshotPath2(String screenshotPath2) { this.screenshotPath2 = screenshotPath2; }
public String getScreenshotPath3() { return screenshotPath3; }
public void setScreenshotPath3(String screenshotPath3) { this.screenshotPath3 = screenshotPath3; }
public boolean isSharedWithAllTenants() { return isSharedWithAllTenants; }
public void setSharedWithAllTenants(boolean sharedWithAllTenants) { isSharedWithAllTenants = sharedWithAllTenants; }
@ -190,4 +172,8 @@ public class ApplicationRelease {
public double getRating() { return rating; }
public void setRating(double rating) { this.rating = rating; }
public List<String> getScreenshots() { return screenshots; }
public void setScreenshots(List<String> screenshots) { this.screenshots = screenshots; }
}

@ -19,6 +19,7 @@
package org.wso2.carbon.device.application.mgt.common.services;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponseTmp;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
@ -32,17 +33,17 @@ public interface SubscriptionManager {
* To install an application to given list of devices.
* @param applicationUUID ID of the application to install
* @param deviceList list of device ID's to install the application
* @return {@link ApplicationInstallResponse} object which contains installed application and devices
* @return {@link ApplicationInstallResponseTmp} object which contains installed application and devices
* @throws ApplicationManagementException if unable to install the application to the given devices
*/
ApplicationInstallResponse installApplicationForDevices(String applicationUUID, List<DeviceIdentifier> deviceList)
ApplicationInstallResponseTmp installApplicationForDevices(String applicationUUID, List<DeviceIdentifier> deviceList)
throws ApplicationManagementException;
/**
* To install an application to given list of users.
* @param applicationUUID ID of the application to install
* @param userList list of users to install the application
* @return {@link ApplicationInstallResponse} object which contains installed application and devices
* @return {@link ApplicationInstallResponseTmp} object which contains installed application and devices
* @throws ApplicationManagementException if unable to install the application to devices belong to given users
*/
ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List<String> userList)
@ -52,20 +53,20 @@ public interface SubscriptionManager {
* To install an application to given list of roles.
* @param applicationUUID ID of the application to install
* @param roleList list of roles to install the application
* @return {@link ApplicationInstallResponse} object which contains installed application and devices
* @return {@link ApplicationInstallResponseTmp} object which contains installed application and devices
* @throws ApplicationManagementException if unable to install the application to devices belong to given roles
*/
ApplicationInstallResponse installApplicationForRoles(String applicationUUID, List<String> roleList)
ApplicationInstallResponseTmp installApplicationForRoles(String applicationUUID, List<String> roleList)
throws ApplicationManagementException;
/**
* To install an application to given list of roles.
* @param applicationUUID ID of the application to install
* @param deviceGroupList list of device groups to install the application
* @return {@link ApplicationInstallResponse} object which contains installed application and devices
* @return {@link ApplicationInstallResponseTmp} object which contains installed application and devices
* @throws ApplicationManagementException if unable to install the application to devices belong to given groups
*/
ApplicationInstallResponse installApplicationForGroups(String applicationUUID, List<String> deviceGroupList)
ApplicationInstallResponseTmp installApplicationForGroups(String applicationUUID, List<String> deviceGroupList)
throws ApplicationManagementException;
/**

@ -25,7 +25,9 @@ import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManageme
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This interface provides the list of operations that are supported with subscription database.
@ -43,9 +45,17 @@ public interface SubscriptionDAO {
* @param releaseId id of the {@link ApplicationReleaseDTO}
* @throws ApplicationManagementDAOException If unable to add a mapping between device and application
*/
void subscribeDeviceToApplication(int tenantId, String subscribedBy, List<Device> deviceList, int appId,
void subscribeDeviceToApplicationTmp(int tenantId, String subscribedBy, List<Device> deviceList, int appId,
int releaseId, String installStatus) throws ApplicationManagementDAOException;
List<Integer> subscribeDeviceToApplication(String subscribedBy, List<Integer> deviceIds, String subscribedFrom,
String installStatus, int releaseId, int tenantId ) throws ApplicationManagementDAOException;
List<Integer> updateDeviceSubscription(String subscribedBy, List<Integer> deviceIds,
String subscribedFrom, String installStatus, int releaseId, int tenantId) throws ApplicationManagementDAOException;
void addOperationMapping (int operationId, List<Integer> deviceSubscriptionId, int tenantId) throws ApplicationManagementDAOException;
/**
* Adds a mapping between user and the application which the application is installed on. This mapping will be
* added when an enterprise installation triggered to the user.
@ -53,11 +63,10 @@ public interface SubscriptionDAO {
* @param tenantId id of the tenant
* @param subscribedBy username of the user who subscribe the application
* @param userList list of user names of the users whose devices are subscribed to the application
* @param appId id of the {@link ApplicationDTO} which installs
* @param releaseId id of the {@link ApplicationReleaseDTO}
* @throws ApplicationManagementDAOException If unable to add a mapping between device and application
*/
void subscribeUserToApplication(int tenantId, String subscribedBy, List<String> userList, int appId, int releaseId)
void subscribeUserToApplication(int tenantId, String subscribedBy, List<String> userList, int releaseId)
throws ApplicationManagementDAOException;
/**
@ -91,4 +100,16 @@ public interface SubscriptionDAO {
List<DeviceSubscriptionDTO> getDeviceSubscriptions(int appReleaseId, int tenantId) throws
ApplicationManagementDAOException;
Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int tenantId) throws
ApplicationManagementDAOException;
List<String> getSubscribedUsernames(List<String> users, int tenantId) throws
ApplicationManagementDAOException;
void updateUserSubscription(int tenantId, String updateBy, boolean isUnsubscribed, List<String> userList,
int releaseId) throws ApplicationManagementDAOException;
List<Integer> getSubscribedDeviceIds(List<Integer> deviceIds, int tenantId) throws ApplicationManagementDAOException;
}

@ -254,7 +254,7 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements
statement.setInt(2, tenantId);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return DAOUtil.loadAppRelease(resultSet);
return DAOUtil.constructAppReleaseDTO(resultSet);
}
return null;
}

@ -32,13 +32,19 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements SubscriptionDAO {
private static Log log = LogFactory.getLog(GenericSubscriptionDAOImpl.class);
@Override
public void subscribeDeviceToApplication(int tenantId, String subscribedBy, List<Device> deviceList, int appId,
public void subscribeDeviceToApplicationTmp(int tenantId, String subscribedBy, List<Device> deviceList, int appId,
int releaseId, String installStatus) throws ApplicationManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
@ -72,36 +78,158 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
}
@Override
public void subscribeUserToApplication(int tenantId, String subscribedBy, List<String> userList, int appId,
int releaseId) throws ApplicationManagementDAOException {
public List<Integer> subscribeDeviceToApplication(String subscribedBy, List<Integer> deviceIds,
String subscribedFrom, String installStatus, int releaseId, int tenantId)
throws ApplicationManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
try {
String sql = "INSERT INTO "
+ "AP_DEVICE_SUBSCRIPTION("
+ "SUBSCRIBED_BY, "
+ "SUBSCRIBED_TIMESTAMP, "
+ "SUBSCRIBED_FROM, "
+ "STATUS, "
+ "DM_DEVICE_ID, "
+ "AP_APP_RELEASE_ID,"
+ "TENANT_ID) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
conn = this.getDBConnection();
long time = System.currentTimeMillis() / 1000;
String sql = "INSERT INTO AP_USER_SUBSCRIPTION(TENANT_ID, SUBSCRIBED_BY, SUBSCRIBED_TIMESTAMP, "
+ "USER_NAME, AP_APP_RELEASE_ID, AP_APP_ID) VALUES (?, ?, ?, ?, ?, ?)";
stmt = conn.prepareStatement(sql);
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
Calendar calendar = Calendar.getInstance();
Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
for (Integer deviceId : deviceIds) {
stmt.setString(1, subscribedBy);
stmt.setTimestamp(2, timestamp);
stmt.setString(3, subscribedFrom);
stmt.setString(4, installStatus);
stmt.setInt(5, deviceId);
stmt.setInt(6, releaseId);
stmt.setInt(7, tenantId);
stmt.addBatch();
if (log.isDebugEnabled()) {
log.debug("Adding a mapping to device[" + deviceId + "] to the application release[" + releaseId
+ "]");
}
}
stmt.executeBatch();
}
} catch (SQLException | DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB",
e);
}
return deviceIds;
}
@Override
public List<Integer> updateDeviceSubscription(String subscribedBy, List<Integer> deviceIds,
String subscribedFrom, String installStatus, int releaseId, int tenantId) throws ApplicationManagementDAOException {
Connection conn;
try {
conn = this.getDBConnection();
String sql = "UPDATE AP_USER_SUBSCRIPTION "
+ "SET "
+ "SUBSCRIBED_BY = ?, "
+ "SUBSCRIBED_TIMESTAMP = ?, "
+ "SUBSCRIBED_FROM = ?, "
+ "STATUS = ? "
+ "WHERE "
+ "DM_DEVICE_ID = ? AND "
+ "AP_APP_RELEASE_ID = ? AND "
+ "TENANT_ID = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
Calendar calendar = Calendar.getInstance();
Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
for (Integer deviceId : deviceIds) {
stmt.setString(1, subscribedBy);
stmt.setTimestamp(2, timestamp);
stmt.setString(3, subscribedFrom);
stmt.setString(4, installStatus);
stmt.setInt(5, deviceId);
stmt.setInt(6, releaseId);
stmt.setInt(7, tenantId);
}
stmt.executeBatch();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to update the device subscriptions of application.";
log.error(msg);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred when obtaining database connection for updating the device subscriptions of application.";
log.error(msg);
throw new ApplicationManagementDAOException(msg, e);
}
return deviceIds;
}
@Override public void addOperationMapping(int operationId, List<Integer> deviceSubscriptionIds, int tenantId)
throws ApplicationManagementDAOException {
Connection conn;
try {
String sql = "INSERT INTO "
+ "AP_APP_SUB_OP_MAPPING("
+ "OPERATION_ID, "
+ "AP_DEVICE_SUBSCRIPTION_ID, "
+ "TENANT_ID) "
+ "VALUES (?, ?, ?, ?, ?)";
conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
for (Integer subId : deviceSubscriptionIds) {
stmt.setInt(1, operationId);
stmt.setInt(2, subId);
stmt.setInt(3, tenantId);
stmt.addBatch();
if (log.isDebugEnabled()) {
log.debug("Adding a operation mapping for subscription id " + subId);
}
}
stmt.executeBatch();
}
} catch (SQLException | DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while adding operation subscription mapping to DB",
e);
}
}
@Override
public void subscribeUserToApplication(int tenantId, String subscribedBy, List<String> userList, int releaseId)
throws ApplicationManagementDAOException {
Connection conn;
try {
String sql = "INSERT INTO "
+ "AP_USER_SUBSCRIPTION("
+ "TENANT_ID, "
+ "SUBSCRIBED_BY, "
+ "SUBSCRIBED_TIMESTAMP, "
+ "USER_NAME, "
+ "AP_APP_RELEASE_ID) "
+ "VALUES (?, ?, ?, ?, ?)";
conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
for (String user : userList) {
stmt = conn.prepareStatement(sql);
Calendar calendar = Calendar.getInstance();
Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
stmt.setInt(1, tenantId);
stmt.setString(2, subscribedBy);
stmt.setLong(3, time);
stmt.setTimestamp(3, timestamp);
stmt.setString(4, user);
stmt.setInt(5, releaseId);
stmt.setInt(6, appId);
stmt.addBatch();
if (log.isDebugEnabled()) {
log.debug("Adding a mapping to user[" + user + "] to the application [" + appId + "], release["
+ releaseId + "]");
log.debug("Adding a mapping to user[" + user + "] to the application release[" + releaseId + "]");
}
}
stmt.executeBatch();
}
} catch (SQLException | DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB",
e);
} finally {
DAOUtil.cleanupResources(stmt, null);
}
}
@ -216,4 +344,165 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
throw new ApplicationManagementDAOException(msg, e);
}
}
@Override
public Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int tenantId)
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get device subscriptions for given device ids.");
}
try {
Connection conn = this.getDBConnection();
int index = 1;
Map<Integer, DeviceSubscriptionDTO> deviceSubscriptionDTOHashMap = new HashMap<>();
StringJoiner joiner = new StringJoiner(",",
"SELECT "
+ "DS.ID AS ID, "
+ "DS.SUBSCRIBED_BY AS SUBSCRIBED_BY, "
+ "DS.SUBSCRIBED_TIMESTAMP AS SUBSCRIBED_AT, "
+ "DS.UNSUBSCRIBED AS IS_UNSUBSCRIBED, "
+ "DS.UNSUBSCRIBED_BY AS UNSUBSCRIBED_BY, "
+ "DS.UNSUBSCRIBED_TIMESTAMP AS UNSUBSCRIBED_AT, "
+ "DS.SUBSCRIBED_FROM AS SUBSCRIBED_FROM, "
+ "DS.DM_DEVICE_ID AS DEVICE_ID, "
+ "DS.STATUS AS STATUS "
+ "FROM AP_DEVICE_SUBSCRIPTION DS "
+ "WHERE DS.DM_DEVICE_ID IN (", ") AND TENANT_ID = ?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index, tenantId);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
DeviceSubscriptionDTO deviceSubscriptionDTO = DAOUtil.constructDeviceSubscriptionDTO(rs);
deviceSubscriptionDTOHashMap.put(deviceSubscriptionDTO.getId(), deviceSubscriptionDTO);
}
}
}
return deviceSubscriptionDTOHashMap;
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when getting device subscriptions for given "
+ "device Ids.", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("SWL Error occurred while getting device subscriptions for given"
+ " device Ids.", e);
}
}
@Override
public List<String> getSubscribedUsernames(List<String> users, int tenantId)
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get already subscribed users for given list of user names.");
}
try {
Connection conn = this.getDBConnection();
int index = 1;
List<String> subscribedUsers = new ArrayList<>();
StringJoiner joiner = new StringJoiner(",",
"SELECT US.USER_NAME AS USER "
+ "FROM AP_USER_SUBSCRIPTION US "
+ "WHERE US.USER_NAME IN (", ") AND TENANT_ID = ?");
users.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (String username : users) {
ps.setObject(index++, username);
}
ps.setInt(index, tenantId);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
subscribedUsers.add(rs.getString("USER"));
}
}
}
return subscribedUsers;
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when getting subscribed users for given "
+ "user names.", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("SWL Error occurred while getting suscribed users for given"
+ " user names.", e);
}
}
@Override public List<Integer> getSubscribedDeviceIds(List<Integer> deviceIds, int tenantId)
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received to DAO Layer to get already subscribed dvice Ids for given list of device Ids.");
}
try {
Connection conn = this.getDBConnection();
int index = 1;
List<Integer> subscribedDevices = new ArrayList<>();
StringJoiner joiner = new StringJoiner(",",
"SELECT DS.DM_DEVICE_ID "
+ "FROM AP_DEVICE_SUBSCRIPTION DS "
+ "WHERE US.DM_DEVICE_ID IN (", ") AND TENANT_ID = ?");
deviceIds.stream().map(ignored -> "?").forEach(joiner::add);
String query = joiner.toString();
try (PreparedStatement ps = conn.prepareStatement(query)) {
for (Integer deviceId : deviceIds) {
ps.setObject(index++, deviceId);
}
ps.setInt(index, tenantId);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
subscribedDevices.add(rs.getInt("DM_DEVICE_I"));
}
}
}
return subscribedDevices;
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when getting subscribed device Ids for given "
+ "device Id list.", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("SWL Error occurred while getting subscribed device ids for "
+ "given devie Id list.", e);
} }
@Override
public void updateUserSubscription(int tenantId, String updateBy, boolean isUnsubscribed,
List<String> userList, int releaseId) throws ApplicationManagementDAOException {
Connection conn;
try {
conn = this.getDBConnection();
String sql = "UPDATE AP_USER_SUBSCRIPTION SET ";
if (isUnsubscribed){
sql += "UNSUBSCRIBED = true, UNSUBSCRIBED_BY = ?, UNSUBSCRIBED_TIMESTAMP ";
} else {
sql += "SUBSCRIBED_BY = ?, SUBSCRIBED_TIMESTAMP =? ";
}
sql += "WHERE USER_NAME = ? AND AP_APP_RELEASE_ID = ? AND AND TENANT_ID = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
Calendar calendar = Calendar.getInstance();
Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
for (String username : userList) {
stmt.setString(1, updateBy);
stmt.setTimestamp(2, timestamp);
stmt.setString(3, username);
stmt.setInt(4, releaseId);
stmt.setInt(5, tenantId);
}
stmt.executeBatch();
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining the DB connection to update the user subscriptions of application.";
log.error(msg);
throw new ApplicationManagementDAOException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred when obtaining database connection for updating the user subscriptions of application.";
log.error(msg);
throw new ApplicationManagementDAOException(msg, e);
}
}
}

@ -2565,7 +2565,9 @@ public class ApplicationManagerImpl implements ApplicationManager {
private ApplicationRelease releaseDtoToRelease(ApplicationReleaseDTO applicationReleaseDTO){
String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration()
.getArtifactDownloadEndpoint();
String basePath = artifactDownloadEndpoint + Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid();
String basePath = artifactDownloadEndpoint + Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid()
+ Constants.FORWARD_SLASH;
List<String> screenshotPaths = new ArrayList<>();
ApplicationRelease applicationRelease = new ApplicationRelease();
applicationRelease.setDescription(applicationReleaseDTO.getDescription());
applicationRelease.setVersion(applicationReleaseDTO.getVersion());
@ -2580,22 +2582,20 @@ public class ApplicationManagerImpl implements ApplicationManager {
applicationRelease.setSupportedOsVersions(applicationReleaseDTO.getSupportedOsVersions());
applicationRelease.setRating(applicationReleaseDTO.getRating());
applicationRelease
.setInstallerPath(basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getInstallerName());
applicationRelease.setIconPath(basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getIconName());
applicationRelease.setBannerPath(basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getBannerName());
.setInstallerPath(basePath + applicationReleaseDTO.getInstallerName());
applicationRelease.setIconPath(basePath + applicationReleaseDTO.getIconName());
applicationRelease.setBannerPath(basePath + applicationReleaseDTO.getBannerName());
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName1())) {
applicationRelease.setScreenshotPath1(
basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getScreenshotName1());
screenshotPaths.add(basePath + applicationReleaseDTO.getScreenshotName1());
}
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName2())) {
applicationRelease.setScreenshotPath2(
basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getScreenshotName2());
screenshotPaths.add(basePath + applicationReleaseDTO.getScreenshotName2());
}
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName3())) {
applicationRelease.setScreenshotPath3(
basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getScreenshotName3());
screenshotPaths.add(basePath + applicationReleaseDTO.getScreenshotName3());
}
applicationRelease.setScreenshots(screenshotPaths);
return applicationRelease;
}

@ -70,13 +70,13 @@ public class MAMDeviceConnectorImpl implements DeviceConnector{
try {
subscriptionDAO.subscribeUserToApplication(appOperation.getTenantId(), appOperation.getSubscribedBy(),
userList, appOperation.getApplication().getId(), appOperation.getAppReleaseId());
userList, appOperation.getAppReleaseId());
for (String username: userList) {
List<Device> devices = getDeviceManagementService().getDevicesOfUser(username);
List<DeviceIdentifier> deviceIdentifiers = convertDeviceToDeviceIdentifier(devices);
// getDeviceManagementService().addOperation(appOperation.getApplication().getDeviceTypeName(),
// operationEKA, devices);
subscriptionDAO.subscribeDeviceToApplication(appOperation.getTenantId(), appOperation.getSubscribedBy(),
subscriptionDAO.subscribeDeviceToApplicationTmp(appOperation.getTenantId(), appOperation.getSubscribedBy(),
devices, appOperation.getApplication().getId(), appOperation.getAppReleaseId(),
String.valueOf(AppOperation.InstallState.PENDING));
}

@ -46,7 +46,6 @@ import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil;
import org.wso2.carbon.device.application.mgt.core.util.Constants;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeMap;

@ -21,15 +21,28 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.application.mgt.common.AppOperation;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO;
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.SubsciptionType;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponseTmp;
import org.wso2.carbon.device.application.mgt.common.dto.DeviceSubscriptionDTO;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException;
import org.wso2.carbon.device.application.mgt.common.exception.LifecycleManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.TransactionManagementException;
import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager;
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO;
import org.wso2.carbon.device.application.mgt.core.dao.SubscriptionDAO;
import org.wso2.carbon.device.application.mgt.core.dao.common.ApplicationManagementDAOFactory;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
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.NotFoundException;
import org.wso2.carbon.device.application.mgt.core.internal.DataHolder;
import org.wso2.carbon.device.application.mgt.core.lifecycle.LifecycleStateManager;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil;
import org.wso2.carbon.device.application.mgt.core.util.HelperUtil;
import org.wso2.carbon.device.mgt.common.Device;
@ -39,14 +52,18 @@ import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
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.OperationManagementException;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
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.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -59,69 +76,225 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
private static final Log log = LogFactory.getLog(SubscriptionManagerImpl.class);
private static final String INSTALL_APPLICATION = "INSTALL_APPLICATION";
private SubscriptionDAO subscriptionDAO;
private ApplicationDAO applicationDAO;
private LifecycleStateManager lifecycleStateManager;
public SubscriptionManagerImpl() {
lifecycleStateManager = DataHolder.getInstance().getLifecycleStateManager();
this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO();
this.applicationDAO = ApplicationManagementDAOFactory.getApplicationDAO();
}
@Override
public ApplicationInstallResponse installApplicationForDevices(String applicationUUID,
List<DeviceIdentifier> deviceList) throws ApplicationManagementException {
public ApplicationInstallResponseTmp installApplicationForDevices(String applicationUUID,
List<DeviceIdentifier> deviceIdentifiers) throws ApplicationManagementException {
if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + deviceList.size() + "devices.");
log.debug("Install application which has UUID: " + applicationUUID + " to " + deviceIdentifiers.size()
+ "devices.");
}
ApplicationDTO applicationDTO = getApplicationDTO(applicationUUID);
validateAppInstallingForDevicesRequest(applicationDTO, deviceIdentifiers);
return installToDevicesTmp(applicationDTO, deviceIdentifiers);
}
ApplicationManager applicationManager = DataHolder.getInstance().getApplicationManager();
ApplicationDTO application = applicationManager.getApplicationByRelease(applicationUUID);
return installApplication(application, deviceList);
private ApplicationDTO getApplicationDTO(String uuid) throws ApplicationManagementException {
ApplicationDTO applicationDTO;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try {
ConnectionManagerUtil.openDBConnection();
applicationDTO = this.applicationDAO.getApplicationByUUID(uuid, tenantId);
if (applicationDTO == null) {
String msg = "Couldn't fond an application for application release UUID: " + uuid;
log.error(msg);
throw new NotFoundException(msg);
}
if (!lifecycleStateManager.getInstallableState()
.equals(applicationDTO.getApplicationReleaseDTOs().get(0).getCurrentState())) {
String msg = "You are trying to install an application which is not in the installable state of "
+ "its Life-Cycle. hence you are not permitted to install this application. If you "
+ "required to install this particular application, please change the state of "
+ "application release from : " + applicationDTO.getApplicationReleaseDTOs().get(0)
.getCurrentState() + " to " + lifecycleStateManager.getInstallableState();
log.error(msg);
throw new ForbiddenException(msg);
}
return applicationDTO;
} catch (LifecycleManagementException e) {
String msg = "Error occured when getting life-cycle state from life-cycle state manager.";
log.error(msg);
throw new ApplicationManagementException(msg);
} catch (ApplicationManagementDAOException e) {
String msg = "Error occurred while getting application data for application release UUID: " + uuid;
log.error(msg);
throw new ApplicationManagementException(msg);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
private void validateAppInstallingForDevicesRequest(ApplicationDTO applicationDTO,
List<DeviceIdentifier> deviceIdentifiers) throws ApplicationManagementException {
DeviceType deviceType = null;
if (!ApplicationType.WEB_CLIP.toString().equals(applicationDTO.getType())) {
deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
}
for (DeviceIdentifier deviceIdentifier : deviceIdentifiers) {
if (!ApplicationType.WEB_CLIP.toString().equals(applicationDTO.getType()) && deviceType != null
&& !deviceType.getName().equals(deviceIdentifier.getType())) {
String msg =
"Found a device identifier which is not matched with the application device Type. Application "
+ "device type is " + deviceType.getName()
+ " and identifier which has different device" + " type is " + deviceIdentifier.getId();
log.error(msg);
throw new BadRequestException(msg);
}
}
}
@Override
public ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List<String> userList)
throws ApplicationManagementException {
public ApplicationInstallResponse installApplicationForUsers(String applicationUUID,
List<String> userList) throws ApplicationManagementException {
if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + userList.size() + " users.");
log.debug("Install application release which has UUID " + applicationUUID + " to " + userList.size()
+ " users.");
}
ApplicationManager applicationManager = DataHolder.getInstance().getApplicationManager();
ApplicationDTO application = applicationManager.getApplicationByRelease(applicationUUID);
List<DeviceIdentifier> deviceList = new ArrayList<>();
//todo check valid user list
ApplicationDTO applicationDTO = getApplicationDTO(applicationUUID);
DeviceType appDeviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId());
List<DeviceIdentifier> operationTriggeredDeviceIdentifiers = new ArrayList<>();
Map<DeviceIdentifier , Integer> compatibleDevices = new HashMap<>();
List<Integer> operationTriggeredDeviceIds = new ArrayList<>();
List<DeviceIdentifier> installedDeviceIdentifiers = new ArrayList<>();
for (String user : userList) {
try {
List<Device> devicesOfUser = HelperUtil.getDeviceManagementProviderService().getDevicesOfUser(user);
devicesOfUser.stream()
.map(device -> new DeviceIdentifier(device.getDeviceIdentifier(), device.getType()))
.forEach(deviceList::add);
if (log.isDebugEnabled()) {
log.debug(devicesOfUser.size() + " found for the provided user list");
List<Device> userDevices = HelperUtil.getDeviceManagementProviderService().getDevicesOfUser(user);
List<Integer> filteredDeviceIds = new ArrayList<>();
List<Device> filteredDevices = new ArrayList<>();
for (Device device : userDevices) {
if (appDeviceType.getName().equals(device.getType())) {
filteredDevices.add(device);
filteredDeviceIds.add(device.getId());
}
}
Map<Integer, DeviceSubscriptionDTO> deviceSubscriptions = getDeviceSubscriptions(filteredDeviceIds);
for (Device device : filteredDevices) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(device.getDeviceIdentifier(),
device.getType());
DeviceSubscriptionDTO deviceSubscriptionDTO = deviceSubscriptions.get(device.getId());
if (deviceSubscriptionDTO != null && !deviceSubscriptionDTO.isUnsubscribed()
&& Operation.Status.COMPLETED.toString().equals(deviceSubscriptionDTO.getStatus())) {
installedDeviceIdentifiers.add(deviceIdentifier);
} else {
compatibleDevices.put(deviceIdentifier, device.getId());
}
}
} catch (DeviceManagementException e) {
throw new ApplicationManagementException("Error when extracting the device list of user[" + user + "].",
e);
String msg = "Error occurred when extracting the device list of user[" + user + "].";
log.error(msg);
throw new ApplicationManagementException(msg, e);
}
}
Activity activity = installToDevices(applicationDTO, new ArrayList<>(compatibleDevices.keySet()),
appDeviceType.getName());
ApplicationInstallResponse response = installApplication(application, deviceList);
List<ActivityStatus> activityStatuses = activity.getActivityStatus();
for (ActivityStatus status : activityStatuses) {
if (status.getStatus().equals(ActivityStatus.Status.PENDING)){
operationTriggeredDeviceIds.add(compatibleDevices.get(status.getDeviceIdentifier()));
operationTriggeredDeviceIdentifiers.add(status.getDeviceIdentifier());
}
}
ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse();
applicationInstallResponse.setActivity(activity);
applicationInstallResponse.setAlreadyInstalledDevices(installedDeviceIdentifiers);
applicationInstallResponse.setInstalledDevices(operationTriggeredDeviceIdentifiers);
int operationId = Integer
.parseInt(activity.getActivityId().split(DeviceManagementConstants.OperationAttributes.ACTIVITY)[1]);
addDeviceSubscriptionForUser(applicationDTO.getApplicationReleaseDTOs().get(0).getId(),
operationTriggeredDeviceIds, userList, operationId);
return applicationInstallResponse;
}
private void addDeviceSubscriptionForUser(int applicationReleaseId, List<Integer> deviceIds, List<String> userList, int operationId)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
int applicationReleaseId = application.getApplicationReleaseDTOs().get(0).getId();
try {
ConnectionManagerUtil.beginDBTransaction();
List<Integer> deviceResubscribingIds = new ArrayList<>();
List<Integer> deviceSubscriptingIds;
List<String> subscribedUsers = subscriptionDAO.getSubscribedUsernames(userList, tenantId);
if (!subscribedUsers.isEmpty()) {
subscriptionDAO
.updateUserSubscription(tenantId, subscriber, false, subscribedUsers, applicationReleaseId);
userList.removeAll(subscribedUsers);
}
subscriptionDAO.subscribeUserToApplication(tenantId, subscriber, userList, applicationReleaseId);
List<Integer> subscribedDevices = subscriptionDAO.getSubscribedDeviceIds(deviceIds, tenantId);
if (!subscribedDevices.isEmpty()) {
deviceResubscribingIds = subscriptionDAO
.updateDeviceSubscription(subscriber, deviceIds, SubsciptionType.USER.toString(),
Operation.Status.PENDING.toString(), applicationReleaseId, tenantId);
deviceIds.removeAll(subscribedDevices);
}
deviceSubscriptingIds = subscriptionDAO
.subscribeDeviceToApplication(subscriber, deviceIds, SubsciptionType.USER.toString(),
Operation.Status.PENDING.toString(), applicationReleaseId, tenantId);
deviceSubscriptingIds.addAll(deviceResubscribingIds);
subscriptionDAO.addOperationMapping(operationId, deviceSubscriptingIds, tenantId);
ConnectionManagerUtil.commitDBTransaction();
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg =
"Error occurred when adding subscription data for application release UUID: " + applicationReleaseId;
log.error(msg);
throw new ApplicationManagementException(msg, e);
} catch (DBConnectionException e) {
String msg = "Error occurred when getting database connection to add new device subscriptions to application.";
log.error(msg);
throw new ApplicationManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg =
"SQL Error occurred when adding new device subscription to application release which has UUID: "
+ applicationReleaseId;
log.error(msg);
throw new ApplicationManagementException(msg, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
private Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions (List<Integer> filteredDeviceIds)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try {
ConnectionManagerUtil.openDBConnection();
subscriptionDAO.subscribeUserToApplication(tenantId, subscriber, userList, application.getId(),
applicationReleaseId);
return this.subscriptionDAO
.getDeviceSubscriptions(filteredDeviceIds, tenantId);
} catch (ApplicationManagementDAOException e) {
//todo
throw new ApplicationManagementException("");
String msg = "Error occured when getting device subscriptions for given device IDs";
log.error(msg);
throw new ApplicationManagementException(msg);
} catch (DBConnectionException e) {
String msg = "Error occured while getting database connection for getting device subscriptions.";
log.error(msg);
throw new ApplicationManagementException(msg);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
return response;
}
@Override
public ApplicationInstallResponse installApplicationForRoles(String applicationUUID, List<String> roleList)
public ApplicationInstallResponseTmp installApplicationForRoles(String applicationUUID, List<String> roleList)
throws ApplicationManagementException {
if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + roleList.size() + " roles.");
@ -144,7 +317,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
}
}
ApplicationInstallResponse response = installApplication(application, deviceList);
ApplicationInstallResponseTmp response = installToDevicesTmp(application, deviceList);
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
@ -165,7 +338,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
}
@Override
public ApplicationInstallResponse installApplicationForGroups(String applicationUUID, List<String> deviceGroupList)
public ApplicationInstallResponseTmp installApplicationForGroups(String applicationUUID, List<String> deviceGroupList)
throws ApplicationManagementException {
if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + deviceGroupList.size() + " groups.");
@ -191,7 +364,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
}
}
ApplicationInstallResponse response = installApplication(application, deviceList);
ApplicationInstallResponseTmp response = installToDevicesTmp(application, deviceList);
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
@ -211,18 +384,36 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return response;
}
@Override
public List<DeviceIdentifier> uninstallApplication(String applicationUUID, List<DeviceIdentifier> deviceList)
throws ApplicationManagementException {
@Override public List<DeviceIdentifier> uninstallApplication(String applicationUUID,
List<DeviceIdentifier> deviceList) throws ApplicationManagementException {
return null;
}
private ApplicationInstallResponse installApplication(ApplicationDTO application,
private Activity installToDevices(ApplicationDTO application,
List<DeviceIdentifier> deviceIdentifierList, String deviceType) throws ApplicationManagementException {
DeviceManagementProviderService deviceManagementProviderService = HelperUtil
.getDeviceManagementProviderService();
try {
Operation operation = generateOperationPayloadByDeviceType(deviceType, application);
//todo refactor add operation code to get successful operations
return deviceManagementProviderService
.addOperation(deviceType, operation, deviceIdentifierList);
} catch (OperationManagementException e) {
throw new ApplicationManagementException("Error occurred while adding the application install "
+ "operation to devices", e);
} catch (InvalidDeviceException e) {
//This exception should not occur because the validation has already been done.
throw new ApplicationManagementException("The list of device identifiers are invalid");
}
}
private ApplicationInstallResponseTmp installToDevicesTmp(ApplicationDTO application,
List<DeviceIdentifier> deviceIdentifierList) throws ApplicationManagementException {
DeviceManagementProviderService deviceManagementProviderService = HelperUtil
.getDeviceManagementProviderService();
ApplicationInstallResponse response = validateDevices(deviceIdentifierList, application.getType());
ApplicationInstallResponseTmp response = validateDevices(deviceIdentifierList);
/*
Group the valid device list by device type. Following lambda expression produces a map containing device type
as the key and the list of device identifiers as the corresponding value.
@ -260,7 +451,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.error("Unable to fetch device for device identifier: " + deviceIdentifier.toString());
}
}
subscriptionDAO.subscribeDeviceToApplication(tenantId, subscriber, deviceList, application.getId(),
subscriptionDAO.subscribeDeviceToApplicationTmp(tenantId, subscriber, deviceList, application.getId(),
applicationReleaseId, String.valueOf(AppOperation.InstallState.UNINSTALLED));
} catch (ApplicationManagementDAOException e) {
//todo
@ -292,30 +483,19 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
* whether the device is enrolled in the system.
*
* @param deviceIdentifierList List of {@link DeviceIdentifier} which the validation happens
* @param appPlatform type of the application
* @return {@link ApplicationInstallResponse} which contains compatible and incompatible device identifiers
* @return {@link ApplicationInstallResponseTmp} which contains compatible and incompatible device identifiers
*/
private ApplicationInstallResponse validateDevices(List<DeviceIdentifier> deviceIdentifierList,
String appPlatform) {
ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse();
private ApplicationInstallResponseTmp validateDevices(List<DeviceIdentifier> deviceIdentifierList) {
ApplicationInstallResponseTmp applicationInstallResponseTmp = new ApplicationInstallResponseTmp();
List<DeviceIdentifier> failedDevices = new ArrayList<>();
List<DeviceIdentifier> compatibleDevices = new ArrayList<>();
for (DeviceIdentifier deviceIdentifier : deviceIdentifierList) {
try {
if (appPlatform == null || !(appPlatform.equals("WEB_CLIP") || appPlatform
.equals(deviceIdentifier.getType()))) {
log.error("Device with ID: [" + deviceIdentifier.getId() + "] of type: ["
+ deviceIdentifier.getType() + "] is not compatible with the application of type: ["
+ appPlatform + "]");
failedDevices.add(deviceIdentifier);
continue;
}
if (!DeviceManagerUtil.isValidDeviceIdentifier(deviceIdentifier)) {
log.error("Device with ID: [" + deviceIdentifier.getId() + "] is not valid to install the "
+ "application.");
applicationInstallResponse.getFailedDevices().add(deviceIdentifier);
applicationInstallResponseTmp.getFailedDevices().add(deviceIdentifier);
}
} catch (DeviceManagementException e) {
log.error("Error occurred while validating the device: [" + deviceIdentifier.getId() + "]", e);
@ -323,9 +503,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
}
compatibleDevices.add(deviceIdentifier);
}
applicationInstallResponse.setFailedDevices(failedDevices);
applicationInstallResponse.setSuccessfulDevices(compatibleDevices);
applicationInstallResponseTmp.setFailedDevices(failedDevices);
applicationInstallResponseTmp.setSuccessfulDevices(compatibleDevices);
return applicationInstallResponse;
return applicationInstallResponseTmp;
}
}

@ -25,9 +25,13 @@ import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.application.mgt.common.Filter;
import org.wso2.carbon.device.application.mgt.common.services.*;
import org.wso2.carbon.device.application.mgt.common.ErrorResponse;
import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException;
import org.wso2.carbon.device.application.mgt.core.exception.UnexpectedServerErrorException;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import javax.ws.rs.core.Response;
import java.util.List;
/**
* Holds util methods required for ApplicationDTO-Mgt API component.
@ -165,29 +169,41 @@ public class APIUtil {
return appmDataHandler;
}
// public static Filter constructFilter( String appName, String appType, String appCategory, String tags,
// boolean isFullMatch, String releaseState, int offset, int limit, String sortBy) {
// Filter filter = new Filter();
// filter.setOffset(offset);
// filter.setLimit(limit);
// filter.setSortBy(sortBy);
// filter.setFullMatch(isFullMatch);
// if (!StringUtils.isEmpty(appName)) {
// filter.setAppName(appName);
// }
// if (!StringUtils.isEmpty(appType)) {
// filter.setAppType(appType);
// }
// if (!StringUtils.isEmpty(appCategory)) {
// filter.setAppCategories(appCategory);
// }
// if (!StringUtils.isEmpty(tags)) {
// filter.setAppCategories(appCategory);
// }
// if (!StringUtils.isEmpty(releaseState)) {
// filter.setAppReleaseState(releaseState);
// }
// return filter;
// }
public static <T> DeviceType getDeviceTypeData(T deviceTypeAttr)
throws BadRequestException, UnexpectedServerErrorException {
List<DeviceType> deviceTypes;
try {
deviceTypes = DAOUtil.getDeviceManagementService().getDeviceTypes();
if(deviceTypeAttr instanceof String){
for (DeviceType dt : deviceTypes) {
if (dt.getName().equals(deviceTypeAttr)) {
return dt;
}
}
} else if (deviceTypeAttr instanceof Integer){
for (DeviceType dt : deviceTypes) {
if (dt.getId() == (Integer) deviceTypeAttr) {
return dt;
}
}
} else {
String msg = "Invalid device type class is received. Device type class: " + deviceTypeAttr.getClass()
.getName();
log.error(msg);
throw new BadRequestException(msg);
}
String msg =
"Invalid device type Attribute is found with the request. Device Type attribute: " + deviceTypeAttr;
log.error(msg);
throw new BadRequestException(msg);
} catch (DeviceManagementException e) {
String msg = "Error occured when getting device types which are supported by the Entgra IoTS";
log.error(msg);
throw new UnexpectedServerErrorException(msg);
}
}
}

@ -83,10 +83,10 @@ public class DAOUtil {
application.setStatus(rs.getString("APP_STATUS"));
application.setAppRating(rs.getDouble("APP_RATING"));
application.setDeviceTypeId(rs.getInt("APP_DEVICE_TYPE_ID"));
application.getApplicationReleaseDTOs().add(loadAppRelease(rs));
application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs));
} else {
if (application != null && application.getApplicationReleaseDTOs() != null) {
application.getApplicationReleaseDTOs().add(loadAppRelease(rs));
application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs));
}
}
hasNext = rs.next();
@ -108,18 +108,23 @@ public class DAOUtil {
public static List<DeviceSubscriptionDTO> loadDeviceSubscriptions(ResultSet rs) throws SQLException {
List<DeviceSubscriptionDTO> deviceSubscriptionDTOS = new ArrayList<>();
while (rs.next()) {
deviceSubscriptionDTOS.add(constructDeviceSubscriptionDTO(rs));
}
return deviceSubscriptionDTOS;
}
public static DeviceSubscriptionDTO constructDeviceSubscriptionDTO(ResultSet rs ) throws SQLException {
DeviceSubscriptionDTO deviceSubscriptionDTO = new DeviceSubscriptionDTO();
deviceSubscriptionDTO.setId(rs.getInt("ID"));
deviceSubscriptionDTO.setSubscribedBy(rs.getString("SUBSCRIBED_BY"));
deviceSubscriptionDTO.setSubscribedTimestamp(rs.getTimestamp("SUBSCRIBED_AT"));
deviceSubscriptionDTO.setUnsubscribed(rs.getBoolean("IS_UNSUBSCRIBED"));
deviceSubscriptionDTO.setUnsubscribedBy(rs.getString("UNSUBSCRIBED_BY"));
deviceSubscriptionDTO.setUnsubscribedTimestapm(rs.getTimestamp("UNSUBSCRIBED_AT"));
deviceSubscriptionDTO.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_AT"));
deviceSubscriptionDTO.setSubscribedFrom(rs.getString("SUBSCRIBED_FROM"));
deviceSubscriptionDTO.setDeviceId(rs.getInt("DEVICE_ID"));
deviceSubscriptionDTOS.add(deviceSubscriptionDTO);
}
return deviceSubscriptionDTOS;
deviceSubscriptionDTO.setStatus(rs.getString("STATUS"));
return deviceSubscriptionDTO;
}
/**
@ -129,7 +134,7 @@ public class DAOUtil {
* @return {@link ApplicationReleaseDTO} object populated with the data
* @throws SQLException If unable to populate {@link ApplicationReleaseDTO} object with the data
*/
public static ApplicationReleaseDTO loadAppRelease(ResultSet rs) throws SQLException {
public static ApplicationReleaseDTO constructAppReleaseDTO(ResultSet rs) throws SQLException {
ApplicationReleaseDTO appRelease = new ApplicationReleaseDTO();
appRelease.setId(rs.getInt("RELEASE_ID"));
appRelease.setDescription(rs.getString("RELEASE_DESCRIPTION"));

@ -29,19 +29,22 @@ 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.dto.ApplicationDTO;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponseTmp;
import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails;
import org.wso2.carbon.device.application.mgt.common.InstallationDetails;
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 tasks.
@ -67,14 +70,14 @@ import javax.ws.rs.core.Response;
@org.wso2.carbon.apimgt.annotations.api.Scope(
name = "Install an ApplicationDTO",
description = "Install an application",
key = "perm:subscription:install",
permissions = {"/device-mgt/subscription/install"}
key = "perm:app:subscription:install",
permissions = {"/app-mgt/store/subscription/install"}
),
@org.wso2.carbon.apimgt.annotations.api.Scope(
name = "Install an ApplicationDTO",
description = "Install an application",
key = "perm:application-mgt:login",
permissions = {"/device-mgt/application-mgt/login"}
name = "Uninstall an Application",
description = "Uninstall an application",
key = "perm:app:subscription:uninstall",
permissions = {"/app-mgt/store/subscription/uninstall"}
)
}
)
@ -87,6 +90,307 @@ public interface SubscriptionManagementAPI {
String SCOPE = "scope";
@POST
@Path("/install/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:install")
})
}
)
@ApiResponses(
value = {
})
Response installApplicationForDevices(
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<DeviceIdentifier> deviceIdentifiers
);
@POST
@Path("/install/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:install")
})
}
)
@ApiResponses(
value = {
})
Response installApplicationForUsers(
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<String> users
);
@POST
@Path("/install/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:install")
})
}
)
@ApiResponses(
value = {
})
Response installApplicationForRoles (
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<String> roles
);
@POST
@Path("/install/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:install")
})
}
)
@ApiResponses(
value = {
})
Response installApplicationForGroups (
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<String> groups
);
// ###########################
@POST
@Path("/uninstall/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall")
})
}
)
@ApiResponses(
value = {
})
Response uninstallApplicationForDevices(
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<DeviceIdentifier> deviceIdentifiers
);
@POST
@Path("/uninstall/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall")
})
}
)
@ApiResponses(
value = {
})
Response uninstallApplicationForUsers(
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<String> users
);
@POST
@Path("/uninstall/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall")
})
}
)
@ApiResponses(
value = {
})
Response uninstallApplicationForRoles (
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<String> roles
);
@POST
@Path("/uninstall/{uuid}/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Install an application for devices",
notes = "This will install an application to a given list of devices",
tags = "Subscription Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall")
})
}
)
@ApiResponses(
value = {
})
Response uninstallApplicationForGroups (
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@PathParam("uuid") String uuid,
@ApiParam(
name = "installationDetails",
value = "The application ID and list of devices/users/roles",
required = true
)
@Valid List<String> groups
);
// ----------------------------------------------
@POST
@Path("/install-application")
@Produces(MediaType.APPLICATION_JSON)
@ -109,7 +413,7 @@ public interface SubscriptionManagementAPI {
@ApiResponse(
code = 200,
message = "OK. \n Successfully sent the install application operation.",
response = ApplicationInstallResponse.class
response = ApplicationInstallResponseTmp.class
),
@ApiResponse(
code = 304,
@ -154,7 +458,7 @@ public interface SubscriptionManagementAPI {
@ApiResponse(
code = 200,
message = "OK. \n Successfully sent the install application operation.",
response = ApplicationInstallResponse.class
response = ApplicationInstallResponseTmp.class
),
@ApiResponse(
code = 304,

@ -23,7 +23,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.ReviewDoesNotExistException;
import org.wso2.carbon.device.application.mgt.common.services.ReviewManager;
import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper;
import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException;

@ -21,17 +21,22 @@ import io.swagger.annotations.ApiParam;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponseTmp;
import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails;
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.NotFoundException;
import org.wso2.carbon.device.application.mgt.store.api.services.SubscriptionManagementAPI;
import org.wso2.carbon.device.application.mgt.common.InstallationDetails;
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.util.APIUtil;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import javax.validation.Valid;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.util.List;
@ -45,6 +50,141 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
private static Log log = LogFactory.getLog(SubscriptionManagementAPIImpl.class);
@Override
@POST
@Path("/install/{uuid}/devices")
public Response installApplicationForDevices(
@PathParam("uuid") String uuid,
@Valid List<DeviceIdentifier> deviceIdentifiers) {
if (deviceIdentifiers.isEmpty()){
String msg = "In order to install application release which has UUID " + uuid + ", you should provide list "
+ "of device identifiers. But found an empty list of identifiers.";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
try {
SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager();
ApplicationInstallResponseTmp response = subscriptionManager
.installApplicationForDevices(uuid, deviceIdentifiers);
return Response.status(Response.Status.OK).entity(response).build();
} catch (NotFoundException e) {
String msg = "Couldn't found an application release for UUI: " + uuid;
log.error(msg);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (BadRequestException e) {
String msg = "Found invalid payload for installing application which has UUID: " + uuid
+ ". Hence verify the payload";
log.error(msg);
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 install the aplication.";
log.error(msg);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
} catch (ApplicationManagementException e) {
String msg =
"Error occurred while installing the application release which has UUID: " + uuid + " for devices";
log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
@Override
@POST
@Path("/install/{uuid}/users")
public Response installApplicationForUsers(
@PathParam("uuid") String uuid,
@Valid List<String> users) {
if (users.isEmpty()){
String msg = "In order to install application release which has UUID " + uuid + ", you should provide list "
+ "of users. But found an empty list of users.";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
try {
SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager();
ApplicationInstallResponse response = subscriptionManager.installApplicationForUsers(uuid, users);
return Response.status(Response.Status.OK).entity(response).build();
//todo
} catch(BadRequestException e){
String msg = "Found invalid payload for installing application which has UUID: " + uuid
+ ". Hence verify the payload";
log.error(msg);
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 install the aplication.";
log.error(msg);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
}catch (ApplicationManagementException e) {
String msg =
"Error occurred while installing the application release which has UUID: " + uuid + " for devices";
log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} }
@Override
@POST
@Path("/install/{uuid}/roles")
public Response installApplicationForRoles(
@PathParam("uuid") String uuid,
@Valid List<String> roles) {
return Response.status(Response.Status.BAD_REQUEST).entity("").build();
}
@Override
@POST
@Path("/install/{uuid}/groups")
public Response installApplicationForGroups(
@PathParam("uuid") String uuid,
@Valid List<String> groups) {
return Response.status(Response.Status.BAD_REQUEST).entity("").build();
}
@Override
@POST
@Path("/uninstall/{uuid}/devices")
public Response uninstallApplicationForDevices(
@PathParam("uuid") String uuid,
@Valid List<DeviceIdentifier> deviceIdentifiers) {
return Response.status(Response.Status.BAD_REQUEST).entity("").build();
}
@Override
@POST
@Path("/uninstall/{uuid}/users")
public Response uninstallApplicationForUsers(
@PathParam("uuid") String uuid,
@Valid List<String> users) {
return Response.status(Response.Status.BAD_REQUEST).entity("").build();
}
@Override
@POST
@Path("/uninstall/{uuid}/roles")
public Response uninstallApplicationForRoles(
@PathParam("uuid") String uuid,
@Valid List<String> roles) {
return Response.status(Response.Status.BAD_REQUEST).entity("").build();
}
@Override
@POST
@Path("/uninstall/{uuid}/groups")
public Response uninstallApplicationForGroups(
@PathParam("uuid") String uuid,
@Valid List<String> groups) {
return Response.status(Response.Status.BAD_REQUEST).entity("").build();
}
@Override
@POST
@Path("/install-application")
@ -61,7 +201,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
}
try {
ApplicationInstallResponse response = subscriptionManager.installApplicationForDevices(applicationUUID,
ApplicationInstallResponseTmp response = subscriptionManager.installApplicationForDevices(applicationUUID,
installationDetails.getDeviceIdentifiers());
return Response.status(Response.Status.OK).entity(response).build();
} catch (ApplicationManagementException e) {
@ -78,7 +218,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
String applicationUUID = enterpriseInstallationDetails.getApplicationUUID();
EnterpriseInstallationDetails.EnterpriseEntity enterpriseEntity = enterpriseInstallationDetails.getEntityType();
List<String> entityValueList = enterpriseInstallationDetails.getEntityValueList();
ApplicationInstallResponse response;
ApplicationInstallResponseTmp response = null;
if (applicationUUID.isEmpty()) {
msg = "ApplicationDTO UUID is empty in the incoming request. Therefore unable to proceed with the "
@ -96,7 +236,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
try {
if (EnterpriseInstallationDetails.EnterpriseEntity.USER.equals(enterpriseEntity)) {
response = subscriptionManager.installApplicationForUsers(applicationUUID, entityValueList);
// response = subscriptionManager.installApplicationForUsers(applicationUUID, entityValueList);
} else if (EnterpriseInstallationDetails.EnterpriseEntity.ROLE.equals(enterpriseEntity)) {
response = subscriptionManager.installApplicationForRoles(applicationUUID, entityValueList);
} else if (EnterpriseInstallationDetails.EnterpriseEntity.DEVICE_GROUP.equals(enterpriseEntity)) {

@ -159,42 +159,48 @@ public class OperationManagerImpl implements OperationManager {
try {
DeviceIDHolder deviceValidationResult = DeviceManagerUtil.validateDeviceIdentifiers(deviceIds);
List<DeviceIdentifier> validDeviceIds = deviceValidationResult.getValidDeviceIDList();
if (!validDeviceIds.isEmpty()) {
if (validDeviceIds.isEmpty()) {
String msg = "Invalid device Identifiers found.";
log.error(msg);
throw new InvalidDeviceException(msg);
}
if (log.isDebugEnabled() && deviceIds.get(0).getType() != null) {
log.debug("Adding operation for Device type : " + deviceIds.get(0).getType() + ", tenant ID:"
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId() + ", domain:"
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()
+ ", device count:" + deviceIds.size() + " operation type:" + operation.getCode());
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain() + ", device count:"
+ deviceIds.size() + " operation type:" + operation.getCode());
}
// Map<Integer, List<DeviceIdentifier>> ignoredDeviceIdentifierMap = new HashMap<>();
// Map<Integer, List<DeviceIdentifier>> authorizedDeviceIdentifierMap = new HashMap<>();
DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds);
List<DeviceIdentifier> authorizedDeviceIds = deviceAuthorizationResult.getValidDeviceIDList();
if (authorizedDeviceIds.size() <= 0) {
if (authorizedDeviceIds.isEmpty()) {
log.warn("User : " + getUser() + " is not authorized to perform operations on given device-list.");
Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations
String deviceType = validDeviceIds.get(0).getType();
activity.setActivityStatus(this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult,
deviceType));
activity.setActivityStatus(
this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult));
return activity;
}
boolean isScheduledOperation = this.isTaskScheduledOperation(operation);
String initiatedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
if (initiatedBy == null && isScheduledOperation) {
if(log.isDebugEnabled()) {
if (log.isDebugEnabled()) {
log.debug("initiatedBy : " + SYSTEM);
}
operation.setInitiatedBy(SYSTEM);
} else {
if(log.isDebugEnabled()) {
if (log.isDebugEnabled()) {
log.debug("initiatedBy : " + initiatedBy);
}
operation.setInitiatedBy(initiatedBy);
}
OperationManagementDAOFactory.beginTransaction();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto =
OperationDAOUtil.convertOperation(operation);
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto = OperationDAOUtil
.convertOperation(operation);
int enrolmentId;
String operationCode = operationDto.getCode();
@ -205,8 +211,8 @@ public class OperationManagerImpl implements OperationManager {
authorizedDevices.add(device);
}
if (operationDto.getControl() ==
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) {
if (operationDto.getControl()
== org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) {
int existingOperationID;
for (Device device : authorizedDevices) {
enrolmentId = device.getEnrolmentInfo().getId();
@ -215,21 +221,31 @@ public class OperationManagerImpl implements OperationManager {
ignoredDevices.add(device);
operation.setId(existingOperationID);
this.sendNotification(operation, device);
// List<DeviceIdentifier> deviceIdentifiers;
// if (ignoredDeviceIdentifierMap.containsKey(existingOperationID)) {
// deviceIdentifiers = ignoredDeviceIdentifierMap.get(existingOperationID);
// } else {
// deviceIdentifiers = new ArrayList<>();
// }
// DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
// deviceIdentifier.setType(device.getType());
// deviceIdentifier.setId(device.getDeviceIdentifier());
// deviceIdentifiers.add(deviceIdentifier);
// ignoredDeviceIdentifierMap.put(existingOperationID, deviceIdentifiers);
}
}
}
if (ignoredDevices.size() > 0) {
if (!ignoredDevices.isEmpty()) {
if (authorizedDevices.size() == ignoredDevices.size()) {
if (log.isDebugEnabled()) {
log.debug("All the devices contain a pending operation for the Operation Code: "
+ operationCode);
log.debug(
"All the devices contain a pending operation for the Operation Code: " + operationCode);
}
Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations
String deviceType = validDeviceIds.get(0).getType();
activity.setActivityStatus(this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult,
deviceType));
activity.setActivityStatus(
this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult));
return activity;
} else {
authorizedDevices.removeAll(ignoredDevices);
@ -244,17 +260,24 @@ public class OperationManagerImpl implements OperationManager {
// check whether device list is greater than batch size notification strategy has enable to send push
// notification using scheduler task
if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceIds.size() &&
notificationStrategy != null) {
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceIds.size()
&& notificationStrategy != null) {
isScheduled = notificationStrategy.getConfig().isScheduled();
}
//TODO have to create a sql to load device details from deviceDAO using single query.
List<DeviceIdentifier> authorizedDeviceIdentifiers = new ArrayList<>();
for (Device device : authorizedDevices) {
enrolmentId = device.getEnrolmentInfo().getId();
//Do not repeat the task operations
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
// DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
// deviceIdentifier.setId(device.getDeviceIdentifier());
// deviceIdentifier.setType(device.getType());
// authorizedDeviceIdentifiers.add(deviceIdentifier);
}
// authorizedDeviceIdentifierMap.put(operationId, authorizedDeviceIdentifiers);
OperationManagementDAOFactory.commitTransaction();
if (!isScheduled) {
@ -270,15 +293,10 @@ public class OperationManagerImpl implements OperationManager {
activity.setType(Activity.Type.valueOf(operationDto.getType().toString()));
//For now set the operation statuses only for admin triggered operations
if (!isScheduledOperation) {
//Get the device-type from 1st valid DeviceIdentifier. We know the 1st element is definitely there.
String deviceType = validDeviceIds.get(0).getType();
activity.setActivityStatus(this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult,
deviceType));
activity.setActivityStatus(
this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult));
}
return activity;
} else {
throw new InvalidDeviceException("Invalid device Identifiers found.");
}
} catch (OperationManagementDAOException e) {
OperationManagementDAOFactory.rollbackTransaction();
throw new OperationManagementException("Error occurred while adding operation", e);
@ -332,22 +350,22 @@ public class OperationManagerImpl implements OperationManager {
}
}
private List<ActivityStatus> getActivityStatus(DeviceIDHolder deviceIdValidationResult, DeviceIDHolder deviceAuthResult,
String deviceType) {
private List<ActivityStatus> getActivityStatus(DeviceIDHolder deviceIdValidationResult,
DeviceIDHolder deviceAuthResult) {
List<ActivityStatus> activityStatuses = new ArrayList<>();
ActivityStatus activityStatus;
//Add the invalid DeviceIds
for (String id : deviceIdValidationResult.getErrorDeviceIdList()) {
for (DeviceIdentifier id : deviceIdValidationResult.getErrorDeviceIdList()) {
activityStatus = new ActivityStatus();
activityStatus.setDeviceIdentifier(new DeviceIdentifier(id, deviceType));
activityStatus.setDeviceIdentifier(id);
activityStatus.setStatus(ActivityStatus.Status.INVALID);
activityStatuses.add(activityStatus);
}
//Add the unauthorized DeviceIds
for (String id : deviceAuthResult.getErrorDeviceIdList()) {
for (DeviceIdentifier id : deviceAuthResult.getErrorDeviceIdList()) {
activityStatus = new ActivityStatus();
activityStatus.setDeviceIdentifier(new DeviceIdentifier(id, deviceType));
activityStatus.setDeviceIdentifier(id);
activityStatus.setStatus(ActivityStatus.Status.UNAUTHORIZED);
activityStatuses.add(activityStatus);
}
@ -365,7 +383,7 @@ public class OperationManagerImpl implements OperationManager {
private DeviceIDHolder authorizeDevices(
Operation operation, List<DeviceIdentifier> deviceIds) throws OperationManagementException {
List<DeviceIdentifier> authorizedDeviceList;
List<String> unAuthorizedDeviceList = new ArrayList<>();
List<DeviceIdentifier> unAuthorizedDeviceList = new ArrayList<>();
DeviceIDHolder deviceIDHolder = new DeviceIDHolder();
try {
if (operation != null && isAuthenticationSkippedOperation(operation)) {
@ -379,7 +397,7 @@ public class OperationManagerImpl implements OperationManager {
if (isAuthorized) {
authorizedDeviceList.add(devId);
} else {
unAuthorizedDeviceList.add(devId.getId());
unAuthorizedDeviceList.add(devId);
}
}
}

@ -27,14 +27,14 @@ import java.util.List;
*/
public class DeviceIDHolder {
private List<String> errorDeviceIdList;
private List<DeviceIdentifier> errorDeviceIdList;
private List<DeviceIdentifier> validDeviceIDList;
public List<String> getErrorDeviceIdList() {
public List<DeviceIdentifier> getErrorDeviceIdList() {
return errorDeviceIdList;
}
public void setErrorDeviceIdList(List<String> errorDeviceIdList) {
public void setErrorDeviceIdList(List<DeviceIdentifier> errorDeviceIdList) {
this.errorDeviceIdList = errorDeviceIdList;
}

@ -464,8 +464,8 @@ public final class DeviceManagerUtil {
public static DeviceIDHolder validateDeviceIdentifiers(List<DeviceIdentifier> deviceIDs) {
List<String> errorDeviceIdList = new ArrayList<String>();
List<DeviceIdentifier> validDeviceIDList = new ArrayList<DeviceIdentifier>();
List<DeviceIdentifier> errorDeviceIdList = new ArrayList<>();
List<DeviceIdentifier> validDeviceIDList = new ArrayList<>();
int deviceIDCounter = 0;
for (DeviceIdentifier deviceIdentifier : deviceIDs) {
@ -474,8 +474,9 @@ public final class DeviceManagerUtil {
String deviceID = deviceIdentifier.getId();
if (deviceID == null || deviceID.isEmpty()) {
errorDeviceIdList.add(String.format(OperationMgtConstants.DeviceConstants.DEVICE_ID_NOT_FOUND,
log.warn(String.format(OperationMgtConstants.DeviceConstants.DEVICE_ID_NOT_FOUND,
deviceIDCounter));
errorDeviceIdList.add(deviceIdentifier);
continue;
}
@ -484,10 +485,10 @@ public final class DeviceManagerUtil {
if (isValidDeviceIdentifier(deviceIdentifier)) {
validDeviceIDList.add(deviceIdentifier);
} else {
errorDeviceIdList.add(deviceID);
errorDeviceIdList.add(deviceIdentifier);
}
} catch (DeviceManagementException e) {
errorDeviceIdList.add(deviceID);
errorDeviceIdList.add(deviceIdentifier);
}
}

@ -110,7 +110,8 @@ CREATE TABLE IF NOT EXISTS AP_DEVICE_SUBSCRIPTION(
UNSUBSCRIBED BOOLEAN NULL DEFAULT NULL,
UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL,
UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL,
SUBSCRIBED_FROM VARCHAR(45) NULL,
SUBSCRIBED_FROM VARCHAR(45) NOT NULL,
STATUS VARCHAR(45) NOT NULL,
DM_DEVICE_ID INTEGER NOT NULL,
AP_APP_RELEASE_ID INTEGER NOT NULL,
AP_APP_ID INTEGER NOT NULL,
@ -247,3 +248,15 @@ CREATE TABLE IF NOT EXISTS AP_APP_CATEGORY_MAPPING(
);
CREATE INDEX fk_AP_APP_CATEGORY_copy1_AP_APP_CATEGORY1_idx ON AP_APP_CATEGORY_MAPPING (AP_APP_CATEGORY_ID ASC);
CREATE INDEX fk_AP_APP_CATEGORY_copy1_AP_APP1_idx ON AP_APP_CATEGORY_MAPPING (AP_APP_ID ASC);
CREATE TABLE IF NOT EXISTS AP_APP_SUB_OP_MAPPING (
ID INTEGER NOT NULL AUTO_INCREMENT,
TENANT_ID INTEGER NOT NULL,
OPERATION_ID INTEGER NOT NULL,
AP_DEVICE_SUBSCRIPTION_ID INTEGER NOT NULL,
PRIMARY KEY (ID),
CONSTRAINT fk_AP_APP_SUB_OP_MAPPING_AP_DEVICE_SUBSCRIPTION1
FOREIGN KEY (AP_DEVICE_SUBSCRIPTION_ID)
REFERENCES AP_DEVICE_SUBSCRIPTION (ID) ON DELETE NO ACTION ON UPDATE NO ACTION
);
CREATE INDEX fk_AP_APP_SUB_OP_MAPPING_AP_DEVICE_SUBSCRIPTION1_idx ON AP_APP_SUB_OP_MAPPING (AP_DEVICE_SUBSCRIPTION_ID ASC);

@ -315,3 +315,18 @@ CREATE TABLE IF NOT EXISTS `APP_MANAGER`.`AP_APP_CATEGORY_MAPPING`
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS `APP_MANAGER`.`AP_APP_OP_DEVICE_MAPPING` (
`ID` INT(11) NOT NULL AUTO_INCREMENT,
`TENANT_ID` INT(11) NOT NULL,
`OPERATION_ID` INT(11) NOT NULL,
`AP_DEVICE_SUBSCRIPTION_ID` INT(11) NOT NULL,
PRIMARY KEY (`ID`),
INDEX `fk_AP_APP_OP_DEVICE_MAPPING_AP_DEVICE_SUBSCRIPTION1_idx` (`AP_DEVICE_SUBSCRIPTION_ID` ASC),
CONSTRAINT `fk_AP_APP_OP_DEVICE_MAPPING_AP_DEVICE_SUBSCRIPTION1`
FOREIGN KEY (`AP_DEVICE_SUBSCRIPTION_ID`)
REFERENCES `APP_MANAGER`.`AP_DEVICE_SUBSCRIPTION` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

Loading…
Cancel
Save