Improve APPM publisher logic

feature/appm-store/pbac
lasanthaDLPDS 6 years ago
parent 05d2e3dab5
commit b440c57147

@ -176,25 +176,23 @@ public interface ApplicationManager {
* @param iconFileStream icon file of the release * @param iconFileStream icon file of the release
* @param bannerFileStream bannerFileStream of the release. * @param bannerFileStream bannerFileStream of the release.
* @param attachments screenshot attachments of the release * @param attachments screenshot attachments of the release
* @return Updated Application Release.
* @throws ApplicationManagementException Application Management Exception. * @throws ApplicationManagementException Application Management Exception.
*/ */
ApplicationRelease updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, InputStream void updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, InputStream
bannerFileStream, List<InputStream> attachments) bannerFileStream, List<InputStream> attachments) throws ApplicationManagementException;
throws ApplicationManagementException, ResourceManagementException;
/** /**
* To update release images. * To update release images.
* *
* @param appId ID of the Application * @param appId ID of the Application
* @param appType Application type
* @param uuid uuid of the Application * @param uuid uuid of the Application
* @param binaryFile binaryFile of the release. * @param binaryFile binaryFile of the release.
* @return Updated Application Release.
* @throws ApplicationManagementException Application Management Exception. * @throws ApplicationManagementException Application Management Exception.
*/ */
ApplicationRelease updateApplicationArtifact(int appId, String uuid, InputStream binaryFile) void updateApplicationArtifact(int appId, String appType, String uuid, InputStream binaryFile)
throws ApplicationManagementException, ResourceManagementException, RequestValidatingException, DeviceManagementException; throws ApplicationManagementException;
/** /**

@ -53,8 +53,7 @@ public interface ApplicationStorageManager {
* @throws ResourceManagementException Resource Management Exception. * @throws ResourceManagementException Resource Management Exception.
*/ */
ApplicationRelease updateImageArtifacts(ApplicationRelease applicationRelease, InputStream iconFile, ApplicationRelease updateImageArtifacts(ApplicationRelease applicationRelease, InputStream iconFile,
InputStream bannerFile, List<InputStream> screenshots) InputStream bannerFile, List<InputStream> screenshots) throws ResourceManagementException;
throws ResourceManagementException, ApplicationManagementException;
/** /**
* To upload release artifacts for an Application. * To upload release artifacts for an Application.

@ -360,7 +360,8 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements
* @param applicationRelease Application Release the properties of which that need to be inserted. * @param applicationRelease Application Release the properties of which that need to be inserted.
* @throws ApplicationManagementDAOException Application Management DAO Exception. * @throws ApplicationManagementDAOException Application Management DAO Exception.
*/ */
@Override public ApplicationRelease updateRelease(int applicationId, ApplicationRelease applicationRelease, int tenantId) @Override
public ApplicationRelease updateRelease(int applicationId, ApplicationRelease applicationRelease, int tenantId)
throws ApplicationManagementDAOException { throws ApplicationManagementDAOException {
Connection connection; Connection connection;
PreparedStatement statement = null; PreparedStatement statement = null;
@ -389,7 +390,9 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements
statement.setInt(15, applicationId); statement.setInt(15, applicationId);
statement.setInt(16, tenantId); statement.setInt(16, tenantId);
statement.setInt(17, applicationRelease.getId()); statement.setInt(17, applicationRelease.getId());
statement.executeUpdate(); if (statement.executeUpdate() == 0) {
return null;
}
} catch (DBConnectionException e) { } catch (DBConnectionException e) {
throw new ApplicationManagementDAOException( throw new ApplicationManagementDAOException(
"Database connection exception while trying to update the application release", e); "Database connection exception while trying to update the application release", e);

@ -33,7 +33,9 @@ import org.wso2.carbon.device.application.mgt.common.Filter;
import org.wso2.carbon.device.application.mgt.common.LifecycleState; import org.wso2.carbon.device.application.mgt.common.LifecycleState;
import org.wso2.carbon.device.application.mgt.common.User; import org.wso2.carbon.device.application.mgt.common.User;
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.ApplicationStorageManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; 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.RequestValidatingException; import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException;
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.TransactionManagementException; import org.wso2.carbon.device.application.mgt.common.exception.TransactionManagementException;
@ -50,6 +52,7 @@ import org.wso2.carbon.device.application.mgt.core.exception.BadRequestException
import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException; import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException;
import org.wso2.carbon.device.application.mgt.core.exception.LifeCycleManagementDAOException; import org.wso2.carbon.device.application.mgt.core.exception.LifeCycleManagementDAOException;
import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException; import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException;
import org.wso2.carbon.device.application.mgt.core.exception.ValidationException;
import org.wso2.carbon.device.application.mgt.core.exception.VisibilityManagementDAOException; import org.wso2.carbon.device.application.mgt.core.exception.VisibilityManagementDAOException;
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.LifecycleStateManger; import org.wso2.carbon.device.application.mgt.core.lifecycle.LifecycleStateManger;
@ -65,7 +68,13 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
/** /**
* Default Concrete implementation of Application Management related implementations. * Default Concrete implementation of Application Management related implementations.
@ -240,10 +249,10 @@ public class ApplicationManagerImpl implements ApplicationManager {
public ApplicationRelease createRelease(int applicationId, ApplicationRelease applicationRelease) public ApplicationRelease createRelease(int applicationId, ApplicationRelease applicationRelease)
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
Application application = getApplicationIfAccessible(applicationId); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
validateAppReleasePayload(applicationRelease); validateAppReleasePayload(applicationRelease);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Application release request is received for the application " + application.toString()); log.debug("Application release request is received for the application id: " + applicationId);
} }
try { try {
ConnectionManagerUtil.beginDBTransaction(); ConnectionManagerUtil.beginDBTransaction();
@ -252,6 +261,19 @@ public class ApplicationManagerImpl implements ApplicationManager {
throw new NotFoundException( throw new NotFoundException(
"Couldn't find application for the application Id: " + applicationId); "Couldn't find application for the application Id: " + applicationId);
} }
// todo check whether admin or app creator.
if (!isAdminUser(userName, tenantId, CarbonConstants.UI_ADMIN_PERMISSION_COLLECTION)) {
String msg = "You don't have permission to create application release for the application id: "
+ applicationId
+ ". In order to create ann new application realse, you should be either ADMIN user or the application created user.";
throw new ForbiddenException(msg);
}
if (!existingApplication.getUnrestrictedRoles().isEmpty() && !isRoleExists(
existingApplication.getUnrestrictedRoles(), userName)) {
String msg = "Application is visible to limited roles and those roles are not assigned to " + userName;
throw new ApplicationManagementException(msg);
}
if (this.applicationReleaseDAO if (this.applicationReleaseDAO
.verifyReleaseExistenceByHash(applicationId, applicationRelease.getAppHashValue(), tenantId)) { .verifyReleaseExistenceByHash(applicationId, applicationRelease.getAppHashValue(), tenantId)) {
throw new BadRequestException("Application release exists for the application Id: " + applicationId throw new BadRequestException("Application release exists for the application Id: " + applicationId
@ -263,7 +285,7 @@ public class ApplicationManagerImpl implements ApplicationManager {
"Package name in the payload is different from the existing package name of other application releases."); "Package name in the payload is different from the existing package name of other application releases.");
} }
applicationRelease = this.applicationReleaseDAO applicationRelease = this.applicationReleaseDAO
.createRelease(applicationRelease, application.getId(), tenantId); .createRelease(applicationRelease, existingApplication.getId(), tenantId);
LifecycleState lifecycleState = getLifecycleStateInstant(AppLifecycleState.CREATED.toString(), LifecycleState lifecycleState = getLifecycleStateInstant(AppLifecycleState.CREATED.toString(),
AppLifecycleState.CREATED.toString()); AppLifecycleState.CREATED.toString());
this.lifecycleStateDAO.addLifecycleState(lifecycleState, applicationId, applicationRelease.getUuid(), tenantId); this.lifecycleStateDAO.addLifecycleState(lifecycleState, applicationId, applicationRelease.getUuid(), tenantId);
@ -282,10 +304,14 @@ public class ApplicationManagerImpl implements ApplicationManager {
} catch (LifeCycleManagementDAOException e) { } catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction(); ConnectionManagerUtil.rollbackDBTransaction();
// todo throws when adding lifecycle state
throw new ApplicationManagementException( throw new ApplicationManagementException(
"Error occurred while adding application release into IoTS app management Application id of the " "Error occurred while adding new application release lifecycle state to the application release: "
+ "application release: " + applicationId, e); + applicationId, e);
} catch (UserStoreException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occurred whecn checking whether user is admin user or not. Application release: "
+ applicationId, e);
} }
} }
@ -306,13 +332,9 @@ public class ApplicationManagerImpl implements ApplicationManager {
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
Application application; Application application;
boolean isAppAllowed = false; boolean isAppAllowed = false;
boolean isOpenConnection = false; List<ApplicationRelease> applicationReleases;
List<ApplicationRelease> applicationReleases = null;
try { try {
if (state != null) {
ConnectionManagerUtil.openDBConnection(); ConnectionManagerUtil.openDBConnection();
isOpenConnection = true;
}
application = this.applicationDAO.getApplicationById(appId, tenantId); application = this.applicationDAO.getApplicationById(appId, tenantId);
if (application == null) { if (application == null) {
throw new NotFoundException("Couldn't find an application for application Id: " + appId); throw new NotFoundException("Couldn't find an application for application Id: " + appId);
@ -341,11 +363,9 @@ public class ApplicationManagerImpl implements ApplicationManager {
throw new ApplicationManagementException( throw new ApplicationManagementException(
"User-store exception while getting application with the application id " + appId); "User-store exception while getting application with the application id " + appId);
} finally { } finally {
if (isOpenConnection) {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.closeDBConnection();
} }
} }
}
@Override @Override
public Application getApplicationByUuid(String uuid, String state) throws ApplicationManagementException { public Application getApplicationByUuid(String uuid, String state) throws ApplicationManagementException {
@ -572,7 +592,8 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ applicationId); + applicationId);
} }
for (ApplicationRelease applicationRelease : applicationReleases) { for (ApplicationRelease applicationRelease : applicationReleases) {
LifecycleState appLifecycleState = getLifecycleState(applicationId, applicationRelease.getUuid()); LifecycleState appLifecycleState = this.lifecycleStateDAO
.getLatestLifeCycleState(applicationId, applicationRelease.getUuid());
LifecycleState newAppLifecycleState = getLifecycleStateInstant(AppLifecycleState.REMOVED.toString(), LifecycleState newAppLifecycleState = getLifecycleStateInstant(AppLifecycleState.REMOVED.toString(),
appLifecycleState.getCurrentState()); appLifecycleState.getCurrentState());
if (lifecycleStateManger.isValidStateChange(newAppLifecycleState.getPreviousState(), if (lifecycleStateManger.isValidStateChange(newAppLifecycleState.getPreviousState(),
@ -581,9 +602,19 @@ public class ApplicationManagerImpl implements ApplicationManager {
.addLifecycleState(newAppLifecycleState, applicationId, applicationRelease.getUuid(), .addLifecycleState(newAppLifecycleState, applicationId, applicationRelease.getUuid(),
tenantId); tenantId);
} else { } else {
// todo move to appropriate lifecycle changing flow and end by remving release String currentState = appLifecycleState.getCurrentState();
List<String> lifecycleFlow = searchLifecycleStateFlow(currentState,
AppLifecycleState.REMOVED.toString());
for (String nextState : lifecycleFlow) {
LifecycleState lifecycleState = getLifecycleStateInstant(nextState, currentState);
if (lifecycleStateManger.isValidStateChange(currentState, nextState)) {
this.lifecycleStateDAO
.addLifecycleState(lifecycleState, applicationId, applicationRelease.getUuid(),
tenantId);
}
currentState = nextState;
}
} }
storedLocations.add(applicationRelease.getAppHashValue()); storedLocations.add(applicationRelease.getAppHashValue());
} }
this.applicationDAO.deleteApplication(applicationId); this.applicationDAO.deleteApplication(applicationId);
@ -595,14 +626,60 @@ public class ApplicationManagerImpl implements ApplicationManager {
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (LifeCycleManagementDAOException e) { } catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction(); ConnectionManagerUtil.rollbackDBTransaction();
// todo String msg = "Error occured while changing the application lifecycle state into REMOVED state.";
String msg = "Error occured while check whether current user has the permission to delete an application";
log.error(msg); log.error(msg);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} }
return storedLocations; return storedLocations;
} }
private List<String> searchLifecycleStateFlow(String start, String finish) throws ApplicationManagementException {
Map<String, String> nextNodeMap = new HashMap<>();
List<String> directions = new LinkedList<>();
Queue<String> queue = new LinkedList<>();
String currentNode = start;
queue.add(currentNode);
Set<String> visitedNodes = new HashSet<>();
visitedNodes.add(currentNode);
while (!queue.isEmpty()) {
currentNode = queue.remove();
if (currentNode.equals(finish)) {
break;
} else {
Set<String> nextStates = lifecycleStateManger.getNextLifecycleStates(currentNode);
if (nextStates.contains(finish)) {
queue = new LinkedList<>();
queue.add(finish);
nextNodeMap.put(currentNode, finish);
} else {
for (String node : nextStates) {
if (!visitedNodes.contains(node)) {
queue.add(node);
visitedNodes.add(node);
nextNodeMap.put(currentNode, node);
}
}
}
}
}
//If all nodes are explored and the destination node hasn't been found.
if (!currentNode.equals(finish)) {
String errorMsg = "can't found a feasible path from " + start + " to " + finish;
throw new ApplicationManagementException(errorMsg);
}
//Reconstruct path
for (String node = start; node != null; node = nextNodeMap.get(node)) {
if (!node.equals(start)) {
directions.add(node);
}
}
return directions;
}
@Override @Override
public String deleteApplicationRelease(int applicationId, String releaseUuid, boolean handleConnections) public String deleteApplicationRelease(int applicationId, String releaseUuid, boolean handleConnections)
throws ApplicationManagementException { throws ApplicationManagementException {
@ -790,96 +867,165 @@ public class ApplicationManagerImpl implements ApplicationManager {
* @param applicationUuid UUID of the Application. * @param applicationUuid UUID of the Application.
* @return Application related with the UUID * @return Application related with the UUID
*/ */
private ApplicationRelease getAppReleaseIfExists(int applicationId, String applicationUuid) throws private ApplicationRelease getAppReleaseIfExists(int applicationId, String applicationUuid)
ApplicationManagementException { throws ValidationException, NotFoundException, ApplicationManagementDAOException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
ApplicationRelease applicationRelease; ApplicationRelease applicationRelease;
if (applicationId <= 0) { if (applicationId <= 0) {
throw new ApplicationManagementException( throw new ValidationException(
"Application id could,t be a negative integer. Hence please add " + "Application id could,t be a negative integer. Hence please add " +
"valid application id."); "valid application id.");
} }
if (applicationUuid == null) { if (applicationUuid == null) {
throw new ApplicationManagementException("Application UUID is null. Application UUID is a required " throw new ValidationException("Application UUID is null. Application UUID is a required "
+ "parameter to get the relevant application."); + "parameter to get the relevant application.");
} }
applicationRelease = this.applicationReleaseDAO.getReleaseByIds(applicationId, applicationUuid, tenantId); applicationRelease = this.applicationReleaseDAO.getReleaseByIds(applicationId, applicationUuid, tenantId);
if (applicationRelease == null) { if (applicationRelease == null) {
log.error("Doesn't exist a application release for application ID: " + applicationId throw new NotFoundException("Doesn't exist a application release for application ID: " + applicationId
+ "and application UUID: " + applicationUuid); + "and application UUID: " + applicationUuid);
} }
return applicationRelease; return applicationRelease;
} }
private ApplicationRelease updateRelease(int appId, ApplicationRelease applicationRelease) throws //todo check whether user is whether admin user or application owner, otherwise throw an exception
ApplicationManagementException { @Override public void updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream,
validateAppReleasePayload(applicationRelease); InputStream bannerFileStream, List<InputStream> attachments) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (log.isDebugEnabled()) {
log.debug("Updating the Application release. UUID: " + applicationRelease.getUuid() + ", " +
"Application Id: " + appId);
}
applicationRelease = this.applicationReleaseDAO.updateRelease(appId, applicationRelease, tenantId);
return applicationRelease;
}
@Override
public ApplicationRelease updateApplicationImageArtifact(int appId, String uuid, InputStream iconFileStream, InputStream
bannerFileStream, List<InputStream> attachments)
throws ApplicationManagementException, ResourceManagementException {
ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager(); ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager();
ApplicationRelease applicationRelease; ApplicationRelease applicationRelease;
try { try {
ConnectionManagerUtil.getDBConnection(); if (appId <= 0) {
applicationRelease = getAppReleaseIfExists(appId, uuid); throw new ValidationException(
"Application id could,t be a negative integer. Hence please add valid application id.");
}
ConnectionManagerUtil.beginDBTransaction();
applicationRelease = this.applicationReleaseDAO.getReleaseByIds(appId, uuid, tenantId);
if (applicationRelease == null) { if (applicationRelease == null) {
throw new NotFoundException("No App release associated with the app Id " + appId + "and UUID "+ uuid); ConnectionManagerUtil.rollbackDBTransaction();
throw new NotFoundException(
"Doesn't exist a application release for application ID: " + appId + "and application UUID: "
+ uuid);
} }
LifecycleState lifecycleState = getLifecycleState(appId, applicationRelease.getUuid()); LifecycleState lifecycleState = this.lifecycleStateDAO
if (AppLifecycleState.PUBLISHED.toString().equals(lifecycleState.getCurrentState()) || .getLatestLifeCycleState(appId, applicationRelease.getUuid());
AppLifecycleState.DEPRECATED.toString().equals(lifecycleState.getCurrentState())) { if (AppLifecycleState.PUBLISHED.toString().equals(lifecycleState.getCurrentState())
throw new ForbiddenException("Can't Update the application release in " + || AppLifecycleState.DEPRECATED.toString().equals(lifecycleState.getCurrentState())) {
"PUBLISHED or DEPRECATED state. Hence please demote the application and update " + ConnectionManagerUtil.rollbackDBTransaction();
"the application release"); throw new ForbiddenException("Can't Update the application release in PUBLISHED or DEPRECATED state. "
+ "Hence please demote the application and update the application release");
} }
ApplicationRelease updatedRelease = applicationStorageManager applicationRelease = applicationStorageManager
.updateImageArtifacts(applicationRelease, iconFileStream, bannerFileStream, attachments); .updateImageArtifacts(applicationRelease, iconFileStream, bannerFileStream, attachments);
return updateRelease(appId, updatedRelease); applicationRelease = this.applicationReleaseDAO.updateRelease(appId, applicationRelease, tenantId);
} finally { if (applicationRelease == null) {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Application release updating count is 0. Application id: " + appId
+ " Application release UUID: " + uuid);
}
ConnectionManagerUtil.commitDBTransaction();
} catch (DBConnectionException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occured when getting DB connection to update image artifacts of the application, appid: "
+ appId + " and uuid " + uuid + ".", e);
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occured while getting application release data for updating image artifacts of the application, appid: "
+ appId + " and uuid " + uuid + ".", e);
} catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occured while getting latest lifecycle state for updating image artifacts of the application, appid: "
+ appId + " and uuid " + uuid + ".", e);
} catch (ResourceManagementException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occured while updating image artifacts of the application, appid: " + appId + " and uuid "
+ uuid + " to the system.", e);
} }
} }
@Override @Override public void updateApplicationArtifact(int appId, String appType, String uuid, InputStream binaryFile)
public ApplicationRelease updateApplicationArtifact(int appId, String uuid, InputStream binaryFile) throws ApplicationManagementException {
throws ApplicationManagementException, ResourceManagementException, RequestValidatingException, DeviceManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager(); ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager();
ApplicationRelease applicationRelease; ApplicationRelease applicationRelease;
try { try {
ConnectionManagerUtil.openDBConnection(); boolean isValidAppType = false;
applicationRelease = getAppReleaseIfExists(appId, uuid);
Application application = getApplicationById(appId, null);
List<DeviceType> deviceTypes = Util.getDeviceManagementService().getDeviceTypes(); List<DeviceType> deviceTypes = Util.getDeviceManagementService().getDeviceTypes();
for (DeviceType deviceType:deviceTypes) { for (DeviceType deviceType : deviceTypes) {
if (deviceType.getId() == application.getDeviceTypeId()) { if (deviceType.getName().equals(appType)) {
application.setDeviceType(deviceType.getName()); isValidAppType = true;
break;
}
}
if (!isValidAppType) {
throw new ValidationException(
"Invalid request to update application release artifact, invalid application type: " + appType
+ " for Application id: " + appId + " application release uuid: " + uuid);
} }
if (appId <= 0) {
throw new ValidationException(
"Application id could,t be a negative integer. Hence please add valid application id. application type: "
+ appType + " Application id: " + appId + " UUID: " + uuid);
}
ConnectionManagerUtil.beginDBTransaction();
Application application = this.applicationDAO.getApplicationById(appId, tenantId);
if (application == null) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new NotFoundException("Doesn't exist a application for the application ID: " + appId);
} }
applicationRelease = this.applicationReleaseDAO.getReleaseByIds(appId, uuid, tenantId);
if (applicationRelease == null) { if (applicationRelease == null) {
throw new NotFoundException("No App release associated with the app Id " + appId + "and UUID "+ uuid); ConnectionManagerUtil.rollbackDBTransaction();
throw new NotFoundException(
"Doesn't exist a application release for application ID: " + appId + "and application UUID: "
+ uuid);
} }
applicationStorageManager applicationRelease = applicationStorageManager
.updateReleaseArtifacts(applicationRelease, application.getType(), application.getDeviceType(), .updateReleaseArtifacts(applicationRelease, application.getType(), application.getDeviceType(),
binaryFile); binaryFile);
updateRelease(appId, applicationRelease); applicationRelease = this.applicationReleaseDAO.updateRelease(appId, applicationRelease, tenantId);
return applicationRelease; if (applicationRelease == null) {
} finally { ConnectionManagerUtil.rollbackDBTransaction();
ConnectionManagerUtil.closeDBConnection(); throw new ApplicationManagementException(
"Application release updating count is 0. Application id: " + appId
+ " Application release UUID: " + uuid);
}
ConnectionManagerUtil.commitDBTransaction();
} catch (ApplicationManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException("Error occured while getting/updating APPM DB.", e);
} catch (TransactionManagementException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occured while starting the transaction to update application release artifact of the application, appid: "
+ appId + " and uuid " + uuid + ".", e);
} catch (RequestValidatingException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException("Error occured while updating application artifact.", e);
} catch (DeviceManagementException e) {
throw new ApplicationManagementException("Error occured while getting supported device types in IoTS", e);
} catch (NotFoundException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Couldn't find application/application elease for appid: " + appId + " and uuid " + uuid + ".", e);
} catch (DBConnectionException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException(
"Error occured when getting DB connection to update application release artifact of the application, appid: "
+ appId + " and uuid " + uuid + ".", e);
} catch (ApplicationStorageManagementException e) {
ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException("In order to update the artifact, couldn't find it in the system",
e);
} }
} }
@ -942,15 +1088,10 @@ public class ApplicationManagerImpl implements ApplicationManager {
ConnectionManagerUtil.openDBConnection(); ConnectionManagerUtil.openDBConnection();
lifecycleState = this.lifecycleStateDAO.getLatestLifeCycleState(applicationId, releaseUuid); lifecycleState = this.lifecycleStateDAO.getLatestLifeCycleState(applicationId, releaseUuid);
if (lifecycleState == null) { if (lifecycleState == null) {
throw new NotFoundException( return null;
"Couldn't find the lifecycle data for appid: " + applicationId + " and app release UUID: "
+ releaseUuid);
} }
lifecycleState.setNextStates(new ArrayList<>(lifecycleStateManger.getNextLifecycleStates(lifecycleState.getCurrentState()))); lifecycleState.setNextStates(new ArrayList<>(lifecycleStateManger.getNextLifecycleStates(lifecycleState.getCurrentState())));
} catch (ApplicationManagementException e) {
throw new ApplicationManagementException("Failed to get application and application management", e);
} catch (LifeCycleManagementDAOException e) { } catch (LifeCycleManagementDAOException e) {
throw new ApplicationManagementException("Failed to get lifecycle state from database", e); throw new ApplicationManagementException("Failed to get lifecycle state from database", e);
} finally { } finally {

@ -164,6 +164,8 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
count++; count++;
} }
} }
applicationRelease = uploadImageArtifacts(applicationRelease, iconFileStream, bannerFileStream,
screenShotStreams);
return applicationRelease; return applicationRelease;
} catch (ApplicationStorageManagementException e) { } catch (ApplicationStorageManagementException e) {
throw new ApplicationStorageManagementException("Application Storage exception while trying to" throw new ApplicationStorageManagementException("Application Storage exception while trying to"
@ -241,16 +243,13 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
return applicationRelease; return applicationRelease;
} }
public InputStream[] cloneInputStream(InputStream inputStream) throws ApplicationStorageManagementException { private InputStream[] cloneInputStream(InputStream inputStream) throws ApplicationStorageManagementException {
ByteArrayOutputStream byteArrayOutputStream = null; try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
try {
byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[BUFFER_SIZE]; byte[] buffer = new byte[BUFFER_SIZE];
int len; int len;
while ((len = inputStream.read(buffer)) > -1 ) { while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len); byteArrayOutputStream.write(buffer, 0, len);
} }
byteArrayOutputStream.flush(); byteArrayOutputStream.flush();
@ -259,17 +258,9 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
InputStream stream2 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); InputStream stream2 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
InputStream stream3 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); InputStream stream3 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return new InputStream[]{stream1, stream2, stream3}; return new InputStream[] { stream1, stream2, stream3 };
} catch (IOException e) { } catch (IOException e) {
throw new ApplicationStorageManagementException("Error occurred while cloning input stream ", e); throw new ApplicationStorageManagementException("Error occurred while cloning input stream ", e);
} finally {
if (byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
}
}
} }
} }
@ -312,7 +303,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
@Override public void deleteAllApplicationReleaseArtifacts(List<String> directoryPaths) @Override public void deleteAllApplicationReleaseArtifacts(List<String> directoryPaths)
throws ApplicationStorageManagementException { throws ApplicationStorageManagementException {
for (String directoryBasePath : directoryPaths) { for (String directoryBasePath : directoryPaths) {
deleteApplicationReleaseArtifacts(directoryBasePath); deleteApplicationReleaseArtifacts(storagePath + directoryBasePath);
} }
} }

@ -443,6 +443,10 @@ public interface ApplicationManagementAPI {
@ApiResponse( @ApiResponse(
code = 200, code = 200,
message = "OK. \n Successfully updated artifacts."), message = "OK. \n Successfully updated artifacts."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Requesting to update image artifacts with invalid application "
+ "or application release data."),
@ApiResponse( @ApiResponse(
code = 403, code = 403,
message = "FORBIDDEN. \n Can't Update the application release in PUBLISHED or DEPRECATED " message = "FORBIDDEN. \n Can't Update the application release in PUBLISHED or DEPRECATED "
@ -519,6 +523,9 @@ public interface ApplicationManagementAPI {
code = 400, code = 400,
message = "Bad Request. \n " + message = "Bad Request. \n " +
"Application artifact updating payload contains unacceptable or vulnerable data"), "Application artifact updating payload contains unacceptable or vulnerable data"),
@ApiResponse(
code = 404,
message = "NOT FOUND. \n Couldn't found application/application release to update applocation release artifact."),
@ApiResponse( @ApiResponse(
code = 500, code = 500,
message = "Internal Server Error. \n Error occurred while getting the application list.", message = "Internal Server Error. \n Error occurred while getting the application list.",

@ -25,6 +25,8 @@ import org.apache.cxf.jaxrs.ext.multipart.Multipart;
import org.wso2.carbon.device.application.mgt.common.*; import org.wso2.carbon.device.application.mgt.common.*;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException; import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException;
import org.wso2.carbon.device.application.mgt.core.exception.ForbiddenException;
import org.wso2.carbon.device.application.mgt.core.exception.ValidationException;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil; import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.application.mgt.publisher.api.services.ApplicationManagementAPI; import org.wso2.carbon.device.application.mgt.publisher.api.services.ApplicationManagementAPI;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
@ -155,7 +157,7 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
} }
try { try {
if (!isValidAppCreatingRequest(iconFile, bannerFile, attachmentList, application)) { if (isInvalidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, application.getType())) {
return Response.status(Response.Status.BAD_REQUEST).build(); return Response.status(Response.Status.BAD_REQUEST).build();
} }
@ -166,11 +168,12 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
.uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(), .uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(),
null); null);
} else { } else {
if (binaryFile == null){ if (application.getApplicationReleases().size() > 1) {
String msg = "Binary file is not found for the application release. Application name: " + application.getName() String msg =
+ " Application type: " + application.getType(); "Invalid application creating request. Application creating request must have single application "
return Response.status(Response.Status.BAD_REQUEST).entity(new ApplicationManagementException(msg)) + "release. Application name:" + application.getName() + " and type: "
.build(); + application.getType();
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} }
applicationRelease = application.getApplicationReleases().get(0); applicationRelease = application.getApplicationReleases().get(0);
applicationRelease = applicationStorageManager applicationRelease = applicationStorageManager
@ -231,7 +234,7 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
@Path("/{deviceType}/{appType}/{appId}") @Path("/{deviceType}/{appType}/{appId}")
public Response createRelease( public Response createRelease(
@PathParam("deviceType") String deviceType, @PathParam("deviceType") String deviceType,
@PathParam("appId") String appType, @PathParam("appType") String appType,
@PathParam("appId") int appId, @PathParam("appId") int appId,
@Multipart("applicationRelease") ApplicationRelease applicationRelease, @Multipart("applicationRelease") ApplicationRelease applicationRelease,
@Multipart("binaryFile") Attachment binaryFile, @Multipart("binaryFile") Attachment binaryFile,
@ -255,7 +258,7 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
} }
try { try {
if (!isValidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, appType)) { if (isInvalidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, appType)) {
return Response.status(Response.Status.BAD_REQUEST).build(); return Response.status(Response.Status.BAD_REQUEST).build();
} }
@ -318,11 +321,13 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Path("/image-artifacts/{appId}/{uuid}") @Path("/image-artifacts/{appId}/{uuid}")
public Response updateApplicationImageArtifacts( public Response updateApplicationImageArtifacts(
@PathParam("appId") int appId, @PathParam("uuid") String applicationUuid, @PathParam("appId") int appId,
@Multipart("icon") Attachment iconFile, @Multipart("banner") Attachment bannerFile, @PathParam("uuid") String applicationReleaseUuid,
@Multipart("screenshot1") Attachment screenshot1, @Multipart("screenshot2") Attachment screenshot2, @Multipart("icon") Attachment iconFile,
@Multipart("banner") Attachment bannerFile,
@Multipart("screenshot1") Attachment screenshot1,
@Multipart("screenshot2") Attachment screenshot2,
@Multipart("screenshot3") Attachment screenshot3) { @Multipart("screenshot3") Attachment screenshot3) {
try { try {
InputStream iconFileStream = null; InputStream iconFileStream = null;
InputStream bannerFileStream = null; InputStream bannerFileStream = null;
@ -334,7 +339,6 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
if (bannerFile != null) { if (bannerFile != null) {
bannerFileStream = bannerFile.getDataHandler().getInputStream(); bannerFileStream = bannerFile.getDataHandler().getInputStream();
} }
attachments.add(screenshot1.getDataHandler().getInputStream()); attachments.add(screenshot1.getDataHandler().getInputStream());
if (screenshot2 != null) { if (screenshot2 != null) {
attachments.add(screenshot2.getDataHandler().getInputStream()); attachments.add(screenshot2.getDataHandler().getInputStream());
@ -343,27 +347,30 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
attachments.add(screenshot3.getDataHandler().getInputStream()); attachments.add(screenshot3.getDataHandler().getInputStream());
} }
ApplicationManager applicationManager = APIUtil.getApplicationManager(); ApplicationManager applicationManager = APIUtil.getApplicationManager();
applicationManager.updateApplicationImageArtifact(appId, applicationUuid, iconFileStream, bannerFileStream, applicationManager
.updateApplicationImageArtifact(appId, applicationReleaseUuid, iconFileStream, bannerFileStream,
attachments); attachments);
return Response.status(Response.Status.OK) return Response.status(Response.Status.OK)
.entity("Successfully uploaded artifacts for the application " + applicationUuid).build(); .entity("Successfully uploaded artifacts for the application " + applicationReleaseUuid).build();
} catch (NotFoundException e) { } catch (NotFoundException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return APIUtil.getResponse(e, Response.Status.NOT_FOUND); return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (ValidationException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (ForbiddenException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build();
} catch (ApplicationManagementException e) { } catch (ApplicationManagementException e) {
String msg = "Error occurred while updating the application."; String msg = "Error occurred while updating the application image artifacts for app id: " + appId
+ " application release uuid: " + applicationReleaseUuid;
log.error(msg, e); log.error(msg, e);
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (IOException e) { } catch (IOException e) {
String msg = "Exception while trying to read icon, banner files for the application " + applicationUuid; String msg =
"Exception while trying to read icon, banner files for the application " + applicationReleaseUuid;
log.error(msg); log.error(msg);
return APIUtil return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
.getResponse(new ApplicationManagementException(msg, e), Response.Status.INTERNAL_SERVER_ERROR);
} catch (ResourceManagementException e) {
log.error("Error occurred while uploading the image artifacts of the application with the uuid "
+ applicationUuid, e);
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
} }
} }
@ -375,41 +382,39 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
@PathParam("deviceType") String deviceType, @PathParam("deviceType") String deviceType,
@PathParam("appType") String appType, @PathParam("appType") String appType,
@PathParam("appId") int applicationId, @PathParam("appId") int applicationId,
@PathParam("uuid") String applicationUuid, @PathParam("uuid") String applicationReleaseUuid,
@Multipart("binaryFile") Attachment binaryFile) { @Multipart("binaryFile") Attachment binaryFile) {
try { try {
if (binaryFile == null) { if (binaryFile == null) {
return APIUtil.getResponse("Uploading artifacts for the application is failed " + applicationUuid, return Response.status(Response.Status.BAD_REQUEST)
Response.Status.BAD_REQUEST); .entity("binary file is NULL, hence invalid request to update application release artifact for application release UUID: "
+ applicationReleaseUuid).build();
} }
APIUtil.getApplicationManager().updateApplicationArtifact(applicationId, applicationUuid, if (!ApplicationType.ENTERPRISE.toString().equals(appType)) {
return Response.status(Response.Status.BAD_REQUEST).entity("If Application type is " + appType
+ ", therefore you don't have application release artifact to update for application release UUID: "
+ applicationReleaseUuid).build();
}
APIUtil.getApplicationManager().updateApplicationArtifact(applicationId, appType, applicationReleaseUuid,
binaryFile.getDataHandler().getInputStream()); binaryFile.getDataHandler().getInputStream());
return Response.status(Response.Status.OK) return Response.status(Response.Status.OK)
.entity("Successfully uploaded artifacts for the application release. UUID is " + applicationUuid) .entity("Successfully uploaded artifacts for the application release. UUID is "
.build(); + applicationReleaseUuid).build();
} catch (IOException e) { } catch (IOException e) {
String msg = "Error occurred while trying to read icon, banner files for the application release" String msg = "Error occurred while trying to read icon, banner files for the application release"
+ applicationUuid; + applicationReleaseUuid;
log.error(msg); log.error(msg);
return APIUtil.getResponse(new ApplicationManagementException(msg, e), Response.Status.BAD_REQUEST); return APIUtil.getResponse(new ApplicationManagementException(msg, e), Response.Status.BAD_REQUEST);
} catch (ResourceManagementException e) { } catch (NotFoundException e) {
log.error("Error occurred while uploading the image artifacts of the application with the uuid " log.error(e.getMessage(), e);
+ applicationUuid, e); return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); } catch (ValidationException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (ApplicationManagementException e) { } catch (ApplicationManagementException e) {
log.error("Error occurred while updating the image artifacts of the application with the uuid " log.error("Error occurred while updating the image artifacts of the application with the uuid "
+ applicationUuid, e); + applicationReleaseUuid, e);
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
} catch (RequestValidatingException e) {
log.error(
"Error occured while handling the application artifact updating request. application release UUID: "
+ applicationUuid);
return APIUtil.getResponse(e, Response.Status.BAD_REQUEST);
} catch (DeviceManagementException e) {
log.error("Error occurred while updating the image artifacts of the application with the uuid "
+ applicationUuid, e);
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR); return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
} }
} }
@ -553,11 +558,12 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
ApplicationManager applicationManager = APIUtil.getApplicationManager(); ApplicationManager applicationManager = APIUtil.getApplicationManager();
try { try {
lifecycleState = applicationManager.getLifecycleState(applicationId, applicationUuid); lifecycleState = applicationManager.getLifecycleState(applicationId, applicationUuid);
} catch (NotFoundException e) { if (lifecycleState == null) {
String msg = "Couldn't found application lifecycle details for appid: " + applicationId String msg = "Couldn't found application lifecycle details for appid: " + applicationId
+ " and app release UUID: " + applicationUuid; + " and app release UUID: " + applicationUuid;
log.error(msg, e); log.error(msg);
return Response.status(Response.Status.NOT_FOUND).build(); return Response.status(Response.Status.NOT_FOUND).build();
}
} catch (ApplicationManagementException e) { } catch (ApplicationManagementException e) {
String msg = "Error occurred while getting lifecycle state."; String msg = "Error occurred while getting lifecycle state.";
log.error(msg, e); log.error(msg, e);
@ -595,60 +601,26 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
return Response.status(Response.Status.CREATED).entity("Lifecycle state added successfully.").build(); return Response.status(Response.Status.CREATED).entity("Lifecycle state added successfully.").build();
} }
private boolean isValidAppCreatingRequest(Attachment iconFile, Attachment bannerFile, private boolean isInvalidReleaseCreatingRequest(Attachment binaryFile, Attachment iconFile, Attachment bannerFile,
List<Attachment> attachmentList, Application application) {
// if (application.getApplicationReleases().size() > 1) {
// log.error("Invalid application creating request. Application creating request must have single application "
// + "release. Application name:" + application.getName() + " and type: " + application.getType());
// return false;
// }
if (iconFile == null) {
log.error("Icon file is not found for the application release. Application name: " + application.getName()
+ " and type: " + application.getType());
return false;
}
if (bannerFile == null) {
log.error("Banner file is not found for the application release. Application name: " + application.getName()
+ " and application type: " + application.getType());
return false;
}
if (attachmentList == null || attachmentList.isEmpty()) {
log.error(
"Screenshots are not found for the application release. Application name: " + application.getName()
+ " Application type: " + application.getType());
return false;
}
return true;
}
private boolean isValidReleaseCreatingRequest(Attachment binaryFile, Attachment iconFile, Attachment bannerFile,
List<Attachment> attachmentList, String appType) { List<Attachment> attachmentList, String appType) {
if (iconFile == null) { if (iconFile == null) {
log.error("Icon file is not found with the application release creating request."); log.error("Icon file is not found with the application release creating request.");
return false; return true;
} }
if (bannerFile == null) { if (bannerFile == null) {
log.error("Banner file is not found with the application release creating request."); log.error("Banner file is not found with the application release creating request.");
return false; return true;
} }
if (attachmentList == null || attachmentList.isEmpty()) { if (attachmentList == null || attachmentList.isEmpty()) {
log.error("Screenshots are not found with the application release creating request."); log.error("Screenshots are not found with the application release creating request.");
return false; return true;
} }
if (binaryFile == null && ApplicationType.ENTERPRISE.toString().equals(appType)) { if (binaryFile == null && ApplicationType.ENTERPRISE.toString().equals(appType)) {
log.error("Binary file is not found with the application release creating request. Application type: " log.error("Binary file is not found with the application release creating request. Application type: "
+ appType); + appType);
return false;
}
return true; return true;
} }
return false;
}
} }

@ -10,6 +10,7 @@
}, },
"license": "Apache License 2.0", "license": "Apache License 2.0",
"dependencies": { "dependencies": {
"acorn": "^6.1.1",
"antd": "^3.15.0", "antd": "^3.15.0",
"react": "^16.8.4", "react": "^16.8.4",
"react-dom": "^16.8.4", "react-dom": "^16.8.4",

Loading…
Cancel
Save