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

feature/appm-store/pbac
Jayasanka 6 years ago
commit 9c9790f2ed

@ -26,18 +26,19 @@ import java.util.List;
public class ApplicationInstallResponse { public class ApplicationInstallResponse {
@ApiModelProperty( @ApiModelProperty(
name = "successfulDevices", name = "installedDevices",
value = "List of successful devices", value = "List of successful devices",
dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]" dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]"
) )
private List<DeviceIdentifier> successfulDevices; private List<DeviceIdentifier> installedDevices;
@ApiModelProperty( @ApiModelProperty(
name = "failedDevices", name = "alreadyInstalledDevices",
value = "List of failed devices", value = "List of devices that application release is already installed.",
dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]" dataType = "List[org.wso2.carbon.device.mgt.common.DeviceIdentifier]"
) )
private List<DeviceIdentifier> failedDevices; private List<DeviceIdentifier> alreadyInstalledDevices;
@ApiModelProperty( @ApiModelProperty(
name = "activity", name = "activity",
@ -45,20 +46,12 @@ public class ApplicationInstallResponse {
) )
private Activity activity; private Activity activity;
public List<DeviceIdentifier> getSuccessfulDevices() { public List<DeviceIdentifier> getInstalledDevices() {
return successfulDevices; return installedDevices;
}
public void setSuccessfulDevices(List<DeviceIdentifier> successfulDevices) {
this.successfulDevices = successfulDevices;
}
public List<DeviceIdentifier> getFailedDevices() {
return failedDevices;
} }
public void setFailedDevices(List<DeviceIdentifier> failedDevices) { public void setInstalledDevices(List<DeviceIdentifier> installedDevices) {
this.failedDevices = failedDevices; this.installedDevices = installedDevices;
} }
public Activity getActivity() { public Activity getActivity() {
@ -68,4 +61,12 @@ public class ApplicationInstallResponse {
public void setActivity(Activity activity) { public void setActivity(Activity activity) {
this.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 Timestamp subscribedTimestamp;
private boolean isUnsubscribed; private boolean isUnsubscribed;
private String unsubscribedBy; private String unsubscribedBy;
private Timestamp unsubscribedTimestapm; private Timestamp unsubscribedTimestamp;
private String subscribedFrom; private String subscribedFrom;
private String status;
private int deviceId; private int deviceId;
public int getId() { return id; } public int getId() { return id; }
@ -52,16 +53,20 @@ public class DeviceSubscriptionDTO {
public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; } public void setUnsubscribedBy(String unsubscribedBy) { this.unsubscribedBy = unsubscribedBy; }
public Timestamp getUnsubscribedTimestapm() { return unsubscribedTimestapm; } public Timestamp getUnsubscribedTimestamp() { return unsubscribedTimestamp; }
public void setUnsubscribedTimestapm(Timestamp unsubscribedTimestapm) { public void setUnsubscribedTimestamp(Timestamp unsubscribedTimestamp) {
this.unsubscribedTimestapm = unsubscribedTimestapm; this.unsubscribedTimestamp = unsubscribedTimestamp;
} }
public String getSubscribedFrom() { return subscribedFrom; } public String getSubscribedFrom() { return subscribedFrom; }
public void setSubscribedFrom(String subscribedFrom) { this.subscribedFrom = 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 int getDeviceId() { return deviceId; }
public void setDeviceId(int deviceId) { this.deviceId = 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.ApiModel;
import io.swagger.annotations.ApiModelProperty; 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") @ApiModel(value = "ApplicationReleaseDTO", description = "This class holds the details when releasing an ApplicationDTO to application store")
public class ApplicationRelease { public class ApplicationRelease {
@ -48,17 +50,9 @@ public class ApplicationRelease {
value = "icon file storing location") value = "icon file storing location")
private String iconPath; private String iconPath;
@ApiModelProperty(name = "screenshotPath1", @ApiModelProperty(name = "screenshots",
value = "Screenshot storing location")
private String screenshotPath1;
@ApiModelProperty(name = "screenshotPath2",
value = "Screenshot storing location") value = "Screenshot storing location")
private String screenshotPath2; private List<String> screenshots;
@ApiModelProperty(name = "screenshotPath3",
value = "Screenshot storing location")
private String screenshotPath3;
@ApiModelProperty(name = "releaseType", @ApiModelProperty(name = "releaseType",
value = "Release type of the application release", value = "Release type of the application release",
@ -163,18 +157,6 @@ public class ApplicationRelease {
public void setIconPath(String iconPath) { this.iconPath = iconPath; } 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 boolean isSharedWithAllTenants() { return isSharedWithAllTenants; }
public void setSharedWithAllTenants(boolean sharedWithAllTenants) { isSharedWithAllTenants = sharedWithAllTenants; } public void setSharedWithAllTenants(boolean sharedWithAllTenants) { isSharedWithAllTenants = sharedWithAllTenants; }
@ -190,4 +172,8 @@ public class ApplicationRelease {
public double getRating() { return rating; } public double getRating() { return rating; }
public void setRating(double rating) { this.rating = 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; 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.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.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
@ -32,17 +33,17 @@ public interface SubscriptionManager {
* To install an application to given list of devices. * To install an application to given list of devices.
* @param applicationUUID ID of the application to install * @param applicationUUID ID of the application to install
* @param deviceList list of device ID's to install the application * @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 * @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; throws ApplicationManagementException;
/** /**
* To install an application to given list of users. * To install an application to given list of users.
* @param applicationUUID ID of the application to install * @param applicationUUID ID of the application to install
* @param userList list of users to install the application * @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 * @throws ApplicationManagementException if unable to install the application to devices belong to given users
*/ */
ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List<String> userList) ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List<String> userList)
@ -52,20 +53,20 @@ public interface SubscriptionManager {
* To install an application to given list of roles. * To install an application to given list of roles.
* @param applicationUUID ID of the application to install * @param applicationUUID ID of the application to install
* @param roleList list of roles to install the application * @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 * @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; throws ApplicationManagementException;
/** /**
* To install an application to given list of roles. * To install an application to given list of roles.
* @param applicationUUID ID of the application to install * @param applicationUUID ID of the application to install
* @param deviceGroupList list of device groups to install the application * @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 * @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; 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.Device;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* This interface provides the list of operations that are supported with subscription database. * 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} * @param releaseId id of the {@link ApplicationReleaseDTO}
* @throws ApplicationManagementDAOException If unable to add a mapping between device and application * @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; 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 * 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. * added when an enterprise installation triggered to the user.
@ -53,11 +63,10 @@ public interface SubscriptionDAO {
* @param tenantId id of the tenant * @param tenantId id of the tenant
* @param subscribedBy username of the user who subscribe the application * @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 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} * @param releaseId id of the {@link ApplicationReleaseDTO}
* @throws ApplicationManagementDAOException If unable to add a mapping between device and application * @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; throws ApplicationManagementDAOException;
/** /**
@ -91,4 +100,16 @@ public interface SubscriptionDAO {
List<DeviceSubscriptionDTO> getDeviceSubscriptions(int appReleaseId, int tenantId) throws List<DeviceSubscriptionDTO> getDeviceSubscriptions(int appReleaseId, int tenantId) throws
ApplicationManagementDAOException; ApplicationManagementDAOException;
Map<Integer, DeviceSubscriptionDTO> getDeviceSubscriptions(List<Integer> deviceIds, int tenantId) throws
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); statement.setInt(2, tenantId);
try (ResultSet resultSet = statement.executeQuery()) { try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) { if (resultSet.next()) {
return DAOUtil.loadAppRelease(resultSet); return DAOUtil.constructAppReleaseDTO(resultSet);
} }
return null; return null;
} }

@ -32,13 +32,19 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; 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.List;
import java.util.Map;
import java.util.StringJoiner;
public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements SubscriptionDAO { public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements SubscriptionDAO {
private static Log log = LogFactory.getLog(GenericSubscriptionDAOImpl.class); private static Log log = LogFactory.getLog(GenericSubscriptionDAOImpl.class);
@Override @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 { int releaseId, String installStatus) throws ApplicationManagementDAOException {
Connection conn; Connection conn;
PreparedStatement stmt = null; PreparedStatement stmt = null;
@ -72,36 +78,158 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
} }
@Override @Override
public void subscribeUserToApplication(int tenantId, String subscribedBy, List<String> userList, int appId, public List<Integer> subscribeDeviceToApplication(String subscribedBy, List<Integer> deviceIds,
int releaseId) throws ApplicationManagementDAOException { String subscribedFrom, String installStatus, int releaseId, int tenantId)
throws ApplicationManagementDAOException {
Connection conn; Connection conn;
PreparedStatement stmt = null;
try { 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(); conn = this.getDBConnection();
long time = System.currentTimeMillis() / 1000; try (PreparedStatement stmt = conn.prepareStatement(sql)) {
String sql = "INSERT INTO AP_USER_SUBSCRIPTION(TENANT_ID, SUBSCRIBED_BY, SUBSCRIBED_TIMESTAMP, " Calendar calendar = Calendar.getInstance();
+ "USER_NAME, AP_APP_RELEASE_ID, AP_APP_ID) VALUES (?, ?, ?, ?, ?, ?)"; Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
stmt = conn.prepareStatement(sql); for (Integer deviceId : deviceIds) {
for (String user : userList) { stmt.setString(1, subscribedBy);
stmt = conn.prepareStatement(sql); stmt.setTimestamp(2, timestamp);
stmt.setInt(1, tenantId); stmt.setString(3, subscribedFrom);
stmt.setString(2, subscribedBy); stmt.setString(4, installStatus);
stmt.setLong(3, time); stmt.setInt(5, deviceId);
stmt.setString(4, user); stmt.setInt(6, releaseId);
stmt.setInt(5, releaseId); stmt.setInt(7, tenantId);
stmt.setInt(6, appId); stmt.addBatch();
stmt.addBatch(); if (log.isDebugEnabled()) {
if (log.isDebugEnabled()) { log.debug("Adding a mapping to device[" + deviceId + "] to the application release[" + releaseId
log.debug("Adding a mapping to user[" + user + "] to the application [" + appId + "], 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) {
Calendar calendar = Calendar.getInstance();
Timestamp timestamp = new Timestamp(calendar.getTime().getTime());
stmt.setInt(1, tenantId);
stmt.setString(2, subscribedBy);
stmt.setTimestamp(3, timestamp);
stmt.setString(4, user);
stmt.setInt(5, releaseId);
stmt.addBatch();
if (log.isDebugEnabled()) {
log.debug("Adding a mapping to user[" + user + "] to the application release[" + releaseId + "]");
}
}
stmt.executeBatch();
} }
stmt.executeBatch();
} catch (SQLException | DBConnectionException e) { } catch (SQLException | DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB", throw new ApplicationManagementDAOException("Error occurred while adding device application mapping to DB",
e); e);
} finally {
DAOUtil.cleanupResources(stmt, null);
} }
} }
@ -216,4 +344,165 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc
throw new ApplicationManagementDAOException(msg, e); 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){ private ApplicationRelease releaseDtoToRelease(ApplicationReleaseDTO applicationReleaseDTO){
String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration() String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration()
.getArtifactDownloadEndpoint(); .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 applicationRelease = new ApplicationRelease();
applicationRelease.setDescription(applicationReleaseDTO.getDescription()); applicationRelease.setDescription(applicationReleaseDTO.getDescription());
applicationRelease.setVersion(applicationReleaseDTO.getVersion()); applicationRelease.setVersion(applicationReleaseDTO.getVersion());
@ -2580,22 +2582,20 @@ public class ApplicationManagerImpl implements ApplicationManager {
applicationRelease.setSupportedOsVersions(applicationReleaseDTO.getSupportedOsVersions()); applicationRelease.setSupportedOsVersions(applicationReleaseDTO.getSupportedOsVersions());
applicationRelease.setRating(applicationReleaseDTO.getRating()); applicationRelease.setRating(applicationReleaseDTO.getRating());
applicationRelease applicationRelease
.setInstallerPath(basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getInstallerName()); .setInstallerPath(basePath + applicationReleaseDTO.getInstallerName());
applicationRelease.setIconPath(basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getIconName()); applicationRelease.setIconPath(basePath + applicationReleaseDTO.getIconName());
applicationRelease.setBannerPath(basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getBannerName()); applicationRelease.setBannerPath(basePath + applicationReleaseDTO.getBannerName());
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName1())) { if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName1())) {
applicationRelease.setScreenshotPath1( screenshotPaths.add(basePath + applicationReleaseDTO.getScreenshotName1());
basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getScreenshotName1());
} }
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName2())) { if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName2())) {
applicationRelease.setScreenshotPath2( screenshotPaths.add(basePath + applicationReleaseDTO.getScreenshotName2());
basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getScreenshotName2());
} }
if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName3())) { if (!StringUtils.isEmpty(applicationReleaseDTO.getScreenshotName3())) {
applicationRelease.setScreenshotPath3( screenshotPaths.add(basePath + applicationReleaseDTO.getScreenshotName3());
basePath + Constants.FORWARD_SLASH + applicationReleaseDTO.getScreenshotName3());
} }
applicationRelease.setScreenshots(screenshotPaths);
return applicationRelease; return applicationRelease;
} }

@ -70,13 +70,13 @@ public class MAMDeviceConnectorImpl implements DeviceConnector{
try { try {
subscriptionDAO.subscribeUserToApplication(appOperation.getTenantId(), appOperation.getSubscribedBy(), subscriptionDAO.subscribeUserToApplication(appOperation.getTenantId(), appOperation.getSubscribedBy(),
userList, appOperation.getApplication().getId(), appOperation.getAppReleaseId()); userList, appOperation.getAppReleaseId());
for (String username: userList) { for (String username: userList) {
List<Device> devices = getDeviceManagementService().getDevicesOfUser(username); List<Device> devices = getDeviceManagementService().getDevicesOfUser(username);
List<DeviceIdentifier> deviceIdentifiers = convertDeviceToDeviceIdentifier(devices); List<DeviceIdentifier> deviceIdentifiers = convertDeviceToDeviceIdentifier(devices);
// getDeviceManagementService().addOperation(appOperation.getApplication().getDeviceTypeName(), // getDeviceManagementService().addOperation(appOperation.getApplication().getDeviceTypeName(),
// operationEKA, devices); // operationEKA, devices);
subscriptionDAO.subscribeDeviceToApplication(appOperation.getTenantId(), appOperation.getSubscribedBy(), subscriptionDAO.subscribeDeviceToApplicationTmp(appOperation.getTenantId(), appOperation.getSubscribedBy(),
devices, appOperation.getApplication().getId(), appOperation.getAppReleaseId(), devices, appOperation.getApplication().getId(), appOperation.getAppReleaseId(),
String.valueOf(AppOperation.InstallState.PENDING)); 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 org.wso2.carbon.device.application.mgt.core.util.Constants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.TreeMap; import java.util.TreeMap;

@ -21,15 +21,28 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.application.mgt.common.AppOperation; 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.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.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.ApplicationManager;
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO;
import org.wso2.carbon.device.application.mgt.core.dao.SubscriptionDAO; 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.dao.common.ApplicationManagementDAOFactory;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; 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.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.ConnectionManagerUtil;
import org.wso2.carbon.device.application.mgt.core.util.HelperUtil; import org.wso2.carbon.device.application.mgt.core.util.HelperUtil;
import org.wso2.carbon.device.mgt.common.Device; 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.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.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.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; 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 Log log = LogFactory.getLog(SubscriptionManagerImpl.class);
private static final String INSTALL_APPLICATION = "INSTALL_APPLICATION"; private static final String INSTALL_APPLICATION = "INSTALL_APPLICATION";
private SubscriptionDAO subscriptionDAO; private SubscriptionDAO subscriptionDAO;
private ApplicationDAO applicationDAO;
private LifecycleStateManager lifecycleStateManager;
public SubscriptionManagerImpl() { public SubscriptionManagerImpl() {
lifecycleStateManager = DataHolder.getInstance().getLifecycleStateManager();
this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO(); this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO();
this.applicationDAO = ApplicationManagementDAOFactory.getApplicationDAO();
} }
@Override @Override
public ApplicationInstallResponse installApplicationForDevices(String applicationUUID, public ApplicationInstallResponseTmp installApplicationForDevices(String applicationUUID,
List<DeviceIdentifier> deviceList) throws ApplicationManagementException { List<DeviceIdentifier> deviceIdentifiers) throws ApplicationManagementException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + deviceList.size() + "devices."); log.debug("Install application which has UUID: " + applicationUUID + " to " + deviceIdentifiers.size()
+ "devices.");
} }
ApplicationManager applicationManager = DataHolder.getInstance().getApplicationManager(); ApplicationDTO applicationDTO = getApplicationDTO(applicationUUID);
ApplicationDTO application = applicationManager.getApplicationByRelease(applicationUUID); validateAppInstallingForDevicesRequest(applicationDTO, deviceIdentifiers);
return installToDevicesTmp(applicationDTO, deviceIdentifiers);
}
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 @Override
public ApplicationInstallResponse installApplicationForUsers(String applicationUUID, List<String> userList) public ApplicationInstallResponse installApplicationForUsers(String applicationUUID,
throws ApplicationManagementException { List<String> userList) throws ApplicationManagementException {
if (log.isDebugEnabled()) { 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); //todo check valid user list
List<DeviceIdentifier> deviceList = new ArrayList<>(); 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) { for (String user : userList) {
try { try {
List<Device> devicesOfUser = HelperUtil.getDeviceManagementProviderService().getDevicesOfUser(user); List<Device> userDevices = HelperUtil.getDeviceManagementProviderService().getDevicesOfUser(user);
devicesOfUser.stream() List<Integer> filteredDeviceIds = new ArrayList<>();
.map(device -> new DeviceIdentifier(device.getDeviceIdentifier(), device.getType())) List<Device> filteredDevices = new ArrayList<>();
.forEach(deviceList::add);
if (log.isDebugEnabled()) { for (Device device : userDevices) {
log.debug(devicesOfUser.size() + " found for the provided user list"); 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) { } catch (DeviceManagementException e) {
throw new ApplicationManagementException("Error when extracting the device list of user[" + user + "].", String msg = "Error occurred when extracting the device list of user[" + user + "].";
e); log.error(msg);
throw new ApplicationManagementException(msg, e);
} }
} }
Activity activity = installToDevices(applicationDTO, new ArrayList<>(compatibleDevices.keySet()),
appDeviceType.getName());
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;
}
ApplicationInstallResponse response = installApplication(application, deviceList); private void addDeviceSubscriptionForUser(int applicationReleaseId, List<Integer> deviceIds, List<String> userList, int operationId)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); 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 { try {
ConnectionManagerUtil.openDBConnection(); ConnectionManagerUtil.openDBConnection();
subscriptionDAO.subscribeUserToApplication(tenantId, subscriber, userList, application.getId(), return this.subscriptionDAO
applicationReleaseId); .getDeviceSubscriptions(filteredDeviceIds, tenantId);
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
//todo String msg = "Error occured when getting device subscriptions for given device IDs";
throw new ApplicationManagementException(""); 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 { } finally {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.closeDBConnection();
} }
return response;
} }
@Override @Override
public ApplicationInstallResponse installApplicationForRoles(String applicationUUID, List<String> roleList) public ApplicationInstallResponseTmp installApplicationForRoles(String applicationUUID, List<String> roleList)
throws ApplicationManagementException { throws ApplicationManagementException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + roleList.size() + " roles."); 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); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
@ -165,7 +338,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
@Override @Override
public ApplicationInstallResponse installApplicationForGroups(String applicationUUID, List<String> deviceGroupList) public ApplicationInstallResponseTmp installApplicationForGroups(String applicationUUID, List<String> deviceGroupList)
throws ApplicationManagementException { throws ApplicationManagementException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Install application: " + applicationUUID + " to " + deviceGroupList.size() + " groups."); 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); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String subscriber = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
@ -211,18 +384,36 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return response; return response;
} }
@Override @Override public List<DeviceIdentifier> uninstallApplication(String applicationUUID,
public List<DeviceIdentifier> uninstallApplication(String applicationUUID, List<DeviceIdentifier> deviceList) List<DeviceIdentifier> deviceList) throws ApplicationManagementException {
throws ApplicationManagementException {
return null; 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 { List<DeviceIdentifier> deviceIdentifierList) throws ApplicationManagementException {
DeviceManagementProviderService deviceManagementProviderService = HelperUtil DeviceManagementProviderService deviceManagementProviderService = HelperUtil
.getDeviceManagementProviderService(); .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 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. 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()); 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)); applicationReleaseId, String.valueOf(AppOperation.InstallState.UNINSTALLED));
} catch (ApplicationManagementDAOException e) { } catch (ApplicationManagementDAOException e) {
//todo //todo
@ -292,30 +483,19 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
* whether the device is enrolled in the system. * whether the device is enrolled in the system.
* *
* @param deviceIdentifierList List of {@link DeviceIdentifier} which the validation happens * @param deviceIdentifierList List of {@link DeviceIdentifier} which the validation happens
* @param appPlatform type of the application * @return {@link ApplicationInstallResponseTmp} which contains compatible and incompatible device identifiers
* @return {@link ApplicationInstallResponse} which contains compatible and incompatible device identifiers
*/ */
private ApplicationInstallResponse validateDevices(List<DeviceIdentifier> deviceIdentifierList, private ApplicationInstallResponseTmp validateDevices(List<DeviceIdentifier> deviceIdentifierList) {
String appPlatform) { ApplicationInstallResponseTmp applicationInstallResponseTmp = new ApplicationInstallResponseTmp();
ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse();
List<DeviceIdentifier> failedDevices = new ArrayList<>(); List<DeviceIdentifier> failedDevices = new ArrayList<>();
List<DeviceIdentifier> compatibleDevices = new ArrayList<>(); List<DeviceIdentifier> compatibleDevices = new ArrayList<>();
for (DeviceIdentifier deviceIdentifier : deviceIdentifierList) { for (DeviceIdentifier deviceIdentifier : deviceIdentifierList) {
try { 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)) { if (!DeviceManagerUtil.isValidDeviceIdentifier(deviceIdentifier)) {
log.error("Device with ID: [" + deviceIdentifier.getId() + "] is not valid to install the " log.error("Device with ID: [" + deviceIdentifier.getId() + "] is not valid to install the "
+ "application."); + "application.");
applicationInstallResponse.getFailedDevices().add(deviceIdentifier); applicationInstallResponseTmp.getFailedDevices().add(deviceIdentifier);
} }
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
log.error("Error occurred while validating the device: [" + deviceIdentifier.getId() + "]", e); log.error("Error occurred while validating the device: [" + deviceIdentifier.getId() + "]", e);
@ -323,9 +503,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
compatibleDevices.add(deviceIdentifier); compatibleDevices.add(deviceIdentifier);
} }
applicationInstallResponse.setFailedDevices(failedDevices); applicationInstallResponseTmp.setFailedDevices(failedDevices);
applicationInstallResponse.setSuccessfulDevices(compatibleDevices); 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.Filter;
import org.wso2.carbon.device.application.mgt.common.services.*; 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.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 javax.ws.rs.core.Response;
import java.util.List;
/** /**
* Holds util methods required for ApplicationDTO-Mgt API component. * Holds util methods required for ApplicationDTO-Mgt API component.
@ -165,29 +169,41 @@ public class APIUtil {
return appmDataHandler; return appmDataHandler;
} }
// public static Filter constructFilter( String appName, String appType, String appCategory, String tags, public static <T> DeviceType getDeviceTypeData(T deviceTypeAttr)
// boolean isFullMatch, String releaseState, int offset, int limit, String sortBy) { throws BadRequestException, UnexpectedServerErrorException {
// Filter filter = new Filter(); List<DeviceType> deviceTypes;
// filter.setOffset(offset); try {
// filter.setLimit(limit); deviceTypes = DAOUtil.getDeviceManagementService().getDeviceTypes();
// filter.setSortBy(sortBy);
// filter.setFullMatch(isFullMatch); if(deviceTypeAttr instanceof String){
// if (!StringUtils.isEmpty(appName)) { for (DeviceType dt : deviceTypes) {
// filter.setAppName(appName); if (dt.getName().equals(deviceTypeAttr)) {
// } return dt;
// if (!StringUtils.isEmpty(appType)) { }
// filter.setAppType(appType); }
// } } else if (deviceTypeAttr instanceof Integer){
// if (!StringUtils.isEmpty(appCategory)) { for (DeviceType dt : deviceTypes) {
// filter.setAppCategories(appCategory); if (dt.getId() == (Integer) deviceTypeAttr) {
// } return dt;
// if (!StringUtils.isEmpty(tags)) { }
// filter.setAppCategories(appCategory); }
// } } else {
// if (!StringUtils.isEmpty(releaseState)) { String msg = "Invalid device type class is received. Device type class: " + deviceTypeAttr.getClass()
// filter.setAppReleaseState(releaseState); .getName();
// } log.error(msg);
// return filter; 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.setStatus(rs.getString("APP_STATUS"));
application.setAppRating(rs.getDouble("APP_RATING")); application.setAppRating(rs.getDouble("APP_RATING"));
application.setDeviceTypeId(rs.getInt("APP_DEVICE_TYPE_ID")); application.setDeviceTypeId(rs.getInt("APP_DEVICE_TYPE_ID"));
application.getApplicationReleaseDTOs().add(loadAppRelease(rs)); application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs));
} else { } else {
if (application != null && application.getApplicationReleaseDTOs() != null) { if (application != null && application.getApplicationReleaseDTOs() != null) {
application.getApplicationReleaseDTOs().add(loadAppRelease(rs)); application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs));
} }
} }
hasNext = rs.next(); hasNext = rs.next();
@ -108,20 +108,25 @@ public class DAOUtil {
public static List<DeviceSubscriptionDTO> loadDeviceSubscriptions(ResultSet rs) throws SQLException { public static List<DeviceSubscriptionDTO> loadDeviceSubscriptions(ResultSet rs) throws SQLException {
List<DeviceSubscriptionDTO> deviceSubscriptionDTOS = new ArrayList<>(); List<DeviceSubscriptionDTO> deviceSubscriptionDTOS = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
DeviceSubscriptionDTO deviceSubscriptionDTO = new DeviceSubscriptionDTO(); deviceSubscriptionDTOS.add(constructDeviceSubscriptionDTO(rs));
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.setSubscribedFrom(rs.getString("SUBSCRIBED_FROM"));
deviceSubscriptionDTO.setDeviceId(rs.getInt("DEVICE_ID"));
deviceSubscriptionDTOS.add(deviceSubscriptionDTO);
} }
return deviceSubscriptionDTOS; 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.setUnsubscribedTimestamp(rs.getTimestamp("UNSUBSCRIBED_AT"));
deviceSubscriptionDTO.setSubscribedFrom(rs.getString("SUBSCRIBED_FROM"));
deviceSubscriptionDTO.setDeviceId(rs.getInt("DEVICE_ID"));
deviceSubscriptionDTO.setStatus(rs.getString("STATUS"));
return deviceSubscriptionDTO;
}
/** /**
* Populates {@link ApplicationReleaseDTO} object with the result obtained from the database. * Populates {@link ApplicationReleaseDTO} object with the result obtained from the database.
* *
@ -129,7 +134,7 @@ public class DAOUtil {
* @return {@link ApplicationReleaseDTO} object populated with the data * @return {@link ApplicationReleaseDTO} object populated with the data
* @throws SQLException If unable to populate {@link ApplicationReleaseDTO} object 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(); ApplicationReleaseDTO appRelease = new ApplicationReleaseDTO();
appRelease.setId(rs.getInt("RELEASE_ID")); appRelease.setId(rs.getInt("RELEASE_ID"));
appRelease.setDescription(rs.getString("RELEASE_DESCRIPTION")); appRelease.setDescription(rs.getString("RELEASE_DESCRIPTION"));

@ -29,19 +29,22 @@ import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag; import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO; 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.EnterpriseInstallationDetails;
import org.wso2.carbon.device.application.mgt.common.InstallationDetails; import org.wso2.carbon.device.application.mgt.common.InstallationDetails;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import javax.validation.Valid; import javax.validation.Valid;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List;
/** /**
* API to handle subscription management related tasks. * API to handle subscription management related tasks.
@ -67,14 +70,14 @@ import javax.ws.rs.core.Response;
@org.wso2.carbon.apimgt.annotations.api.Scope( @org.wso2.carbon.apimgt.annotations.api.Scope(
name = "Install an ApplicationDTO", name = "Install an ApplicationDTO",
description = "Install an application", description = "Install an application",
key = "perm:subscription:install", key = "perm:app:subscription:install",
permissions = {"/device-mgt/subscription/install"} permissions = {"/app-mgt/store/subscription/install"}
), ),
@org.wso2.carbon.apimgt.annotations.api.Scope( @org.wso2.carbon.apimgt.annotations.api.Scope(
name = "Install an ApplicationDTO", name = "Uninstall an Application",
description = "Install an application", description = "Uninstall an application",
key = "perm:application-mgt:login", key = "perm:app:subscription:uninstall",
permissions = {"/device-mgt/application-mgt/login"} permissions = {"/app-mgt/store/subscription/uninstall"}
) )
} }
) )
@ -87,6 +90,307 @@ public interface SubscriptionManagementAPI {
String SCOPE = "scope"; 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 @POST
@Path("/install-application") @Path("/install-application")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ -109,7 +413,7 @@ public interface SubscriptionManagementAPI {
@ApiResponse( @ApiResponse(
code = 200, code = 200,
message = "OK. \n Successfully sent the install application operation.", message = "OK. \n Successfully sent the install application operation.",
response = ApplicationInstallResponse.class response = ApplicationInstallResponseTmp.class
), ),
@ApiResponse( @ApiResponse(
code = 304, code = 304,
@ -154,7 +458,7 @@ public interface SubscriptionManagementAPI {
@ApiResponse( @ApiResponse(
code = 200, code = 200,
message = "OK. \n Successfully sent the install application operation.", message = "OK. \n Successfully sent the install application operation.",
response = ApplicationInstallResponse.class response = ApplicationInstallResponseTmp.class
), ),
@ApiResponse( @ApiResponse(
code = 304, code = 304,

@ -23,7 +23,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.common.PaginationResult; 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.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.services.ReviewManager;
import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper; import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper;
import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException; 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.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse;
import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponseTmp;
import org.wso2.carbon.device.application.mgt.common.EnterpriseInstallationDetails; 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.store.api.services.SubscriptionManagementAPI;
import org.wso2.carbon.device.application.mgt.common.InstallationDetails; 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.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager; import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil; import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import javax.validation.Valid; import javax.validation.Valid;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List; import java.util.List;
@ -45,6 +50,141 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
private static Log log = LogFactory.getLog(SubscriptionManagementAPIImpl.class); 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 @Override
@POST @POST
@Path("/install-application") @Path("/install-application")
@ -61,7 +201,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
} }
try { try {
ApplicationInstallResponse response = subscriptionManager.installApplicationForDevices(applicationUUID, ApplicationInstallResponseTmp response = subscriptionManager.installApplicationForDevices(applicationUUID,
installationDetails.getDeviceIdentifiers()); installationDetails.getDeviceIdentifiers());
return Response.status(Response.Status.OK).entity(response).build(); return Response.status(Response.Status.OK).entity(response).build();
} catch (ApplicationManagementException e) { } catch (ApplicationManagementException e) {
@ -78,7 +218,7 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
String applicationUUID = enterpriseInstallationDetails.getApplicationUUID(); String applicationUUID = enterpriseInstallationDetails.getApplicationUUID();
EnterpriseInstallationDetails.EnterpriseEntity enterpriseEntity = enterpriseInstallationDetails.getEntityType(); EnterpriseInstallationDetails.EnterpriseEntity enterpriseEntity = enterpriseInstallationDetails.getEntityType();
List<String> entityValueList = enterpriseInstallationDetails.getEntityValueList(); List<String> entityValueList = enterpriseInstallationDetails.getEntityValueList();
ApplicationInstallResponse response; ApplicationInstallResponseTmp response = null;
if (applicationUUID.isEmpty()) { if (applicationUUID.isEmpty()) {
msg = "ApplicationDTO UUID is empty in the incoming request. Therefore unable to proceed with the " 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 { try {
if (EnterpriseInstallationDetails.EnterpriseEntity.USER.equals(enterpriseEntity)) { if (EnterpriseInstallationDetails.EnterpriseEntity.USER.equals(enterpriseEntity)) {
response = subscriptionManager.installApplicationForUsers(applicationUUID, entityValueList); // response = subscriptionManager.installApplicationForUsers(applicationUUID, entityValueList);
} else if (EnterpriseInstallationDetails.EnterpriseEntity.ROLE.equals(enterpriseEntity)) { } else if (EnterpriseInstallationDetails.EnterpriseEntity.ROLE.equals(enterpriseEntity)) {
response = subscriptionManager.installApplicationForRoles(applicationUUID, entityValueList); response = subscriptionManager.installApplicationForRoles(applicationUUID, entityValueList);
} else if (EnterpriseInstallationDetails.EnterpriseEntity.DEVICE_GROUP.equals(enterpriseEntity)) { } else if (EnterpriseInstallationDetails.EnterpriseEntity.DEVICE_GROUP.equals(enterpriseEntity)) {

@ -159,126 +159,144 @@ public class OperationManagerImpl implements OperationManager {
try { try {
DeviceIDHolder deviceValidationResult = DeviceManagerUtil.validateDeviceIdentifiers(deviceIds); DeviceIDHolder deviceValidationResult = DeviceManagerUtil.validateDeviceIdentifiers(deviceIds);
List<DeviceIdentifier> validDeviceIds = deviceValidationResult.getValidDeviceIDList(); List<DeviceIdentifier> validDeviceIds = deviceValidationResult.getValidDeviceIDList();
if (!validDeviceIds.isEmpty()) {
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());
}
DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds);
List<DeviceIdentifier> authorizedDeviceIds = deviceAuthorizationResult.getValidDeviceIDList();
if (authorizedDeviceIds.size() <= 0) {
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));
return activity;
}
boolean isScheduledOperation = this.isTaskScheduledOperation(operation); if (validDeviceIds.isEmpty()) {
String initiatedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String msg = "Invalid device Identifiers found.";
if (initiatedBy == null && isScheduledOperation) { log.error(msg);
if(log.isDebugEnabled()) { throw new InvalidDeviceException(msg);
log.debug("initiatedBy : " + SYSTEM); }
} if (log.isDebugEnabled() && deviceIds.get(0).getType() != null) {
operation.setInitiatedBy(SYSTEM); log.debug("Adding operation for Device type : " + deviceIds.get(0).getType() + ", tenant ID:"
} else { + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId() + ", domain:"
if(log.isDebugEnabled()) { + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain() + ", device count:"
log.debug("initiatedBy : " + initiatedBy); + deviceIds.size() + " operation type:" + operation.getCode());
} }
operation.setInitiatedBy(initiatedBy); // 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.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
activity.setActivityStatus(
this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult));
return activity;
}
OperationManagementDAOFactory.beginTransaction(); boolean isScheduledOperation = this.isTaskScheduledOperation(operation);
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto = String initiatedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
OperationDAOUtil.convertOperation(operation); if (initiatedBy == null && isScheduledOperation) {
int enrolmentId; if (log.isDebugEnabled()) {
String operationCode = operationDto.getCode(); log.debug("initiatedBy : " + SYSTEM);
}
List<Device> authorizedDevices = new ArrayList<>(); operation.setInitiatedBy(SYSTEM);
List<Device> ignoredDevices = new ArrayList<>(); } else {
for (DeviceIdentifier deviceId : authorizedDeviceIds) { if (log.isDebugEnabled()) {
Device device = getDevice(deviceId); log.debug("initiatedBy : " + initiatedBy);
authorizedDevices.add(device);
} }
operation.setInitiatedBy(initiatedBy);
}
OperationManagementDAOFactory.beginTransaction();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto = OperationDAOUtil
.convertOperation(operation);
int enrolmentId;
String operationCode = operationDto.getCode();
List<Device> authorizedDevices = new ArrayList<>();
List<Device> ignoredDevices = new ArrayList<>();
for (DeviceIdentifier deviceId : authorizedDeviceIds) {
Device device = getDevice(deviceId);
authorizedDevices.add(device);
}
if (operationDto.getControl() == if (operationDto.getControl()
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) { == org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) {
int existingOperationID; int existingOperationID;
for (Device device : authorizedDevices) { for (Device device : authorizedDevices) {
enrolmentId = device.getEnrolmentInfo().getId(); enrolmentId = device.getEnrolmentInfo().getId();
existingOperationID = operationDAO.getExistingOperationID(enrolmentId, operationCode); existingOperationID = operationDAO.getExistingOperationID(enrolmentId, operationCode);
if (existingOperationID > 0) { if (existingOperationID > 0) {
ignoredDevices.add(device); ignoredDevices.add(device);
operation.setId(existingOperationID); operation.setId(existingOperationID);
this.sendNotification(operation, device); 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 (authorizedDevices.size() == ignoredDevices.size()) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("All the devices contain a pending operation for the Operation Code: " log.debug(
+ operationCode); "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));
return activity;
} else {
authorizedDevices.removeAll(ignoredDevices);
} }
Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations
activity.setActivityStatus(
this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult));
return activity;
} else {
authorizedDevices.removeAll(ignoredDevices);
} }
}
int operationId = this.lookupOperationDAO(operation).addOperation(operationDto); int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
boolean isScheduled = false; boolean isScheduled = false;
NotificationStrategy notificationStrategy = getNotificationStrategy(); NotificationStrategy notificationStrategy = getNotificationStrategy();
// check whether device list is greater than batch size notification strategy has enable to send push // check whether device list is greater than batch size notification strategy has enable to send push
// notification using scheduler task // notification using scheduler task
if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig(). if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceIds.size() && getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceIds.size()
notificationStrategy != null) { && notificationStrategy != null) {
isScheduled = notificationStrategy.getConfig().isScheduled(); isScheduled = notificationStrategy.getConfig().isScheduled();
} }
//TODO have to create a sql to load device details from deviceDAO using single query. //TODO have to create a sql to load device details from deviceDAO using single query.
for (Device device : authorizedDevices) { List<DeviceIdentifier> authorizedDeviceIdentifiers = new ArrayList<>();
enrolmentId = device.getEnrolmentInfo().getId(); for (Device device : authorizedDevices) {
//Do not repeat the task operations enrolmentId = device.getEnrolmentInfo().getId();
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); //Do not repeat the task operations
} operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
OperationManagementDAOFactory.commitTransaction(); // DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
// deviceIdentifier.setId(device.getDeviceIdentifier());
// deviceIdentifier.setType(device.getType());
// authorizedDeviceIdentifiers.add(deviceIdentifier);
}
if (!isScheduled) { // authorizedDeviceIdentifierMap.put(operationId, authorizedDeviceIdentifiers);
for (Device device : authorizedDevices) { OperationManagementDAOFactory.commitTransaction();
this.sendNotification(operation, device);
}
}
Activity activity = new Activity(); if (!isScheduled) {
activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId); for (Device device : authorizedDevices) {
activity.setCode(operationCode); this.sendNotification(operation, device);
activity.setCreatedTimeStamp(new Date().toString());
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));
} }
return activity;
} else {
throw new InvalidDeviceException("Invalid device Identifiers found.");
} }
Activity activity = new Activity();
activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId);
activity.setCode(operationCode);
activity.setCreatedTimeStamp(new Date().toString());
activity.setType(Activity.Type.valueOf(operationDto.getType().toString()));
//For now set the operation statuses only for admin triggered operations
if (!isScheduledOperation) {
activity.setActivityStatus(
this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult));
}
return activity;
} catch (OperationManagementDAOException e) { } catch (OperationManagementDAOException e) {
OperationManagementDAOFactory.rollbackTransaction(); OperationManagementDAOFactory.rollbackTransaction();
throw new OperationManagementException("Error occurred while adding operation", e); 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, private List<ActivityStatus> getActivityStatus(DeviceIDHolder deviceIdValidationResult,
String deviceType) { DeviceIDHolder deviceAuthResult) {
List<ActivityStatus> activityStatuses = new ArrayList<>(); List<ActivityStatus> activityStatuses = new ArrayList<>();
ActivityStatus activityStatus; ActivityStatus activityStatus;
//Add the invalid DeviceIds //Add the invalid DeviceIds
for (String id : deviceIdValidationResult.getErrorDeviceIdList()) { for (DeviceIdentifier id : deviceIdValidationResult.getErrorDeviceIdList()) {
activityStatus = new ActivityStatus(); activityStatus = new ActivityStatus();
activityStatus.setDeviceIdentifier(new DeviceIdentifier(id, deviceType)); activityStatus.setDeviceIdentifier(id);
activityStatus.setStatus(ActivityStatus.Status.INVALID); activityStatus.setStatus(ActivityStatus.Status.INVALID);
activityStatuses.add(activityStatus); activityStatuses.add(activityStatus);
} }
//Add the unauthorized DeviceIds //Add the unauthorized DeviceIds
for (String id : deviceAuthResult.getErrorDeviceIdList()) { for (DeviceIdentifier id : deviceAuthResult.getErrorDeviceIdList()) {
activityStatus = new ActivityStatus(); activityStatus = new ActivityStatus();
activityStatus.setDeviceIdentifier(new DeviceIdentifier(id, deviceType)); activityStatus.setDeviceIdentifier(id);
activityStatus.setStatus(ActivityStatus.Status.UNAUTHORIZED); activityStatus.setStatus(ActivityStatus.Status.UNAUTHORIZED);
activityStatuses.add(activityStatus); activityStatuses.add(activityStatus);
} }
@ -365,7 +383,7 @@ public class OperationManagerImpl implements OperationManager {
private DeviceIDHolder authorizeDevices( private DeviceIDHolder authorizeDevices(
Operation operation, List<DeviceIdentifier> deviceIds) throws OperationManagementException { Operation operation, List<DeviceIdentifier> deviceIds) throws OperationManagementException {
List<DeviceIdentifier> authorizedDeviceList; List<DeviceIdentifier> authorizedDeviceList;
List<String> unAuthorizedDeviceList = new ArrayList<>(); List<DeviceIdentifier> unAuthorizedDeviceList = new ArrayList<>();
DeviceIDHolder deviceIDHolder = new DeviceIDHolder(); DeviceIDHolder deviceIDHolder = new DeviceIDHolder();
try { try {
if (operation != null && isAuthenticationSkippedOperation(operation)) { if (operation != null && isAuthenticationSkippedOperation(operation)) {
@ -379,7 +397,7 @@ public class OperationManagerImpl implements OperationManager {
if (isAuthorized) { if (isAuthorized) {
authorizedDeviceList.add(devId); authorizedDeviceList.add(devId);
} else { } else {
unAuthorizedDeviceList.add(devId.getId()); unAuthorizedDeviceList.add(devId);
} }
} }
} }

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

@ -464,8 +464,8 @@ public final class DeviceManagerUtil {
public static DeviceIDHolder validateDeviceIdentifiers(List<DeviceIdentifier> deviceIDs) { public static DeviceIDHolder validateDeviceIdentifiers(List<DeviceIdentifier> deviceIDs) {
List<String> errorDeviceIdList = new ArrayList<String>(); List<DeviceIdentifier> errorDeviceIdList = new ArrayList<>();
List<DeviceIdentifier> validDeviceIDList = new ArrayList<DeviceIdentifier>(); List<DeviceIdentifier> validDeviceIDList = new ArrayList<>();
int deviceIDCounter = 0; int deviceIDCounter = 0;
for (DeviceIdentifier deviceIdentifier : deviceIDs) { for (DeviceIdentifier deviceIdentifier : deviceIDs) {
@ -474,8 +474,9 @@ public final class DeviceManagerUtil {
String deviceID = deviceIdentifier.getId(); String deviceID = deviceIdentifier.getId();
if (deviceID == null || deviceID.isEmpty()) { 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)); deviceIDCounter));
errorDeviceIdList.add(deviceIdentifier);
continue; continue;
} }
@ -484,10 +485,10 @@ public final class DeviceManagerUtil {
if (isValidDeviceIdentifier(deviceIdentifier)) { if (isValidDeviceIdentifier(deviceIdentifier)) {
validDeviceIDList.add(deviceIdentifier); validDeviceIDList.add(deviceIdentifier);
} else { } else {
errorDeviceIdList.add(deviceID); errorDeviceIdList.add(deviceIdentifier);
} }
} catch (DeviceManagementException e) { } 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 BOOLEAN NULL DEFAULT NULL,
UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL,
UNSUBSCRIBED_TIMESTAMP TIMESTAMP 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, DM_DEVICE_ID INTEGER NOT NULL,
AP_APP_RELEASE_ID INTEGER NOT NULL, AP_APP_RELEASE_ID INTEGER NOT NULL,
AP_APP_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_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 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 ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8; 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