From 5cb706f24b6c0c598ee5b03bb45a2ac91c460071 Mon Sep 17 00:00:00 2001 From: Inosh Perara Date: Fri, 4 Oct 2019 03:08:35 +0000 Subject: [PATCH] Add android enterprise support for IoTS. --- .../common/dto/ApiRegistrationProfile.java | 59 +++ .../mgt/common/dto/ApplicationDTO.java | 12 + .../mgt/common/dto/ApplicationPolicyDTO.java | 44 ++ .../mgt/common/response/Application.java | 12 + .../common/services/ApplicationManager.java | 2 + .../pom.xml | 9 + .../mgt/core/dao/ApplicationReleaseDAO.java | 5 +- .../GenericApplicationReleaseDAOImpl.java | 87 +++- .../mgt/core/impl/ApplicationManagerImpl.java | 83 +++- .../core/impl/SubscriptionManagerImpl.java | 99 ++++- .../application/mgt/core/util/APIUtil.java | 1 + .../application/mgt/core/util/Constants.java | 26 ++ .../application/mgt/core/util/DAOUtil.java | 1 + .../application/mgt/core/util/OAuthUtils.java | 90 ++++ .../react-app/package.json | 11 +- .../react-app/public/conf/config.json | 7 +- .../react-app/src/App.js | 27 +- .../AppDetailsDrawer/AppDetailsDrawer.js | 27 ++ .../apps/release/edit-release/EditRelease.js | 2 +- .../AddNewPage/AddNewPage.js | 125 ++++++ .../android-enterprise/GooglePlayIframe.js | 81 ++++ .../ManagedConfigurationsIframe.js | 224 ++++++++++ .../AddAppsToClusterModal.js | 122 ++++++ .../Pages/Cluster/Cluster.css | 168 +++++++ .../Pages/Cluster/Cluster.js | 410 ++++++++++++++++++ .../Pages/EditLinks/EditLinks.js | 118 +++++ .../manage/android-enterprise/Pages/Pages.css | 33 ++ .../manage/android-enterprise/Pages/Pages.js | 263 +++++++++++ .../android-enterprise/SyncAndroidApps.js | 79 ++++ .../src/components/new-app/AddNewAppForm.js | 7 +- .../new-app/subForms/NewAppUploadForm.js | 2 +- .../components/new-release/AddReleaseForm.js | 9 +- .../react-app/src/index.html | 1 + .../react-app/src/index.js | 12 + .../react-app/src/js/Utils.js | 32 ++ .../src/pages/dashboard/Dashboard.js | 24 +- .../src/pages/dashboard/manage/Manage.js | 23 +- .../ManageAndroidEnterprise.js | 68 +++ .../manage/android-enterprise/page/Page.js | 396 +++++++++++++++++ .../react-app/webpack.config.js | 2 +- .../jaggeryapps/devicemgt/api/enterprise.jag | 132 ++++++ .../modules/business-controllers/policy.js | 1 + .../jaggeryapps/devicemgt/jaggery.conf | 4 + .../request/interceptor/InvokerHandler.java | 2 +- .../ui/request/interceptor/LoginHandler.java | 5 +- .../interceptor/util/HandlerConstants.java | 2 +- .../main/resources/conf/application-mgt.xml | 39 ++ .../dbscripts/cdm/application-mgt/h2.sql | 2 +- .../dbscripts/cdm/application-mgt/mysql.sql | 2 +- .../dbscripts/cdm/application-mgt/oracle.sql | 2 +- .../cdm/application-mgt/postgresql.sql | 2 +- 51 files changed, 2909 insertions(+), 87 deletions(-) create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApiRegistrationProfile.java create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationPolicyDTO.java create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/OAuthUtils.java create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/AddNewPage/AddNewPage.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/GooglePlayIframe.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/ManagedConfigurationsIframe/ManagedConfigurationsIframe.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/Pages/Cluster/AddAppsToClusterModal/AddAppsToClusterModal.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/Pages/Cluster/Cluster.css create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/Pages/Cluster/Cluster.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/Pages/EditLinks/EditLinks.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/Pages/Pages.css create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/Pages/Pages.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/SyncAndroidApps.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/js/Utils.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/pages/dashboard/manage/android-enterprise/ManageAndroidEnterprise.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/pages/dashboard/manage/android-enterprise/page/Page.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/api/enterprise.jag diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApiRegistrationProfile.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApiRegistrationProfile.java new file mode 100644 index 0000000000..a117584bd8 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApiRegistrationProfile.java @@ -0,0 +1,59 @@ +/* + * 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; + +public class ApiRegistrationProfile { + + private String applicationName; + private String tags[]; + private boolean isAllowedToAllDomains; + private boolean isMappingAnExistingOAuthApp; + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public String[] getTags() { + return tags; + } + + public void setTags(String[] tags) { + this.tags = tags; + } + + public boolean isAllowedToAllDomains() { + return isAllowedToAllDomains; + } + + public void setAllowedToAllDomains(boolean allowedToAllDomains) { + isAllowedToAllDomains = allowedToAllDomains; + } + + public boolean isMappingAnExistingOAuthApp() { + return isMappingAnExistingOAuthApp; + } + + public void setMappingAnExistingOAuthApp(boolean mappingAnExistingOAuthApp) { + isMappingAnExistingOAuthApp = mappingAnExistingOAuthApp; + } +} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationDTO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationDTO.java index 108e1e8763..e676c79754 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationDTO.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationDTO.java @@ -94,6 +94,18 @@ public class ApplicationDTO { required = true) private List applicationReleaseDTOs; + @ApiModelProperty(name = "packageName", + value = "package name of the application") + private String packageName; + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + public int getId() { return id; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationPolicyDTO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationPolicyDTO.java new file mode 100644 index 0000000000..f5b630d80a --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/dto/ApplicationPolicyDTO.java @@ -0,0 +1,44 @@ +package org.wso2.carbon.device.application.mgt.common.dto; + +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; + +import java.util.List; + +public class ApplicationPolicyDTO { + ApplicationDTO applicationDTO; + String policy; + List deviceIdentifierList; + String action; + + public List getDeviceIdentifierList() { + return deviceIdentifierList; + } + + public void setDeviceIdentifierList(List deviceIdentifierList) { + this.deviceIdentifierList = deviceIdentifierList; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public ApplicationDTO getApplicationDTO() { + return applicationDTO; + } + + public void setApplicationDTO(ApplicationDTO applicationDTO) { + this.applicationDTO = applicationDTO; + } + + public String getPolicy() { + return policy; + } + + public void setPolicy(String policy) { + this.policy = policy; + } +} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/response/Application.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/response/Application.java index 568a6d186b..aaffc1225b 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/response/Application.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/response/Application.java @@ -82,6 +82,18 @@ public class Application { required = true) private List applicationReleases; + @ApiModelProperty(name = "packageName", + value = "package name of the application") + private String packageName; + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + public int getId() { return id; } public void setId(int id) { this.id = id; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java index 116de80c91..a8d9af300c 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/ApplicationManager.java @@ -273,4 +273,6 @@ public interface ApplicationManager { */ String getPlistArtifact(String uuid) throws ApplicationManagementException; + List getReleaseByPackageNames(List packageIds) throws ApplicationManagementException; + } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml index dc5cbbc1df..ebd105472c 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/pom.xml @@ -80,6 +80,10 @@ org.apache.commons.codec.digest;version="${commons-codec.wso2.osgi.version.range}", org.wso2.carbon.base, com.dd.*, + org.wso2.carbon.identity.jwt.client.extension.*, + org.wso2.carbon.apimgt.application.extension.*, + org.apache.commons.httpclient, + org.apache.commons.httpclient.methods, org.apache.commons.validator.routines apk-parser;scope=compile|runtime;inline=false @@ -240,6 +244,11 @@ test + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.application.extension + + diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationReleaseDAO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationReleaseDAO.java index edc75ca569..9fc7c642d5 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationReleaseDAO.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/ApplicationReleaseDAO.java @@ -117,4 +117,7 @@ public interface ApplicationReleaseDAO { boolean hasExistInstallableAppRelease(String releaseUuid, String installableStateName, int tenantId) throws ApplicationManagementDAOException; - } + List getReleaseByPackages(List packages, int tenantId) + throws ApplicationManagementDAOException; + +} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java index 47f85b4361..979a28c2f0 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/application/release/GenericApplicationReleaseDAOImpl.java @@ -1,4 +1,4 @@ -/* + /* * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, @@ -36,8 +36,9 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.StringJoiner; -/** + /** * GenericApplicationReleaseDAOImpl holds the implementation of ApplicationRelease related DAO operations. */ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements ApplicationReleaseDAO { @@ -278,9 +279,15 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements + "APP_HASH_VALUE = ?, " + "SHARED_WITH_ALL_TENANTS = ?, " + "APP_META_INFO = ?, " - + "SUPPORTED_OS_VERSIONS = ?, " - + "CURRENT_STATE = ? " - + "WHERE ID = ? AND TENANT_ID = ? "; + + "SUPPORTED_OS_VERSIONS = ?"; + + if (applicationReleaseDTO.getCurrentState() != null) { + sql += ", CURRENT_STATE = ? "; + } + + sql += " WHERE ID = ? AND TENANT_ID = ? "; + + int x = 17; try { Connection connection = this.getDBConnection(); try (PreparedStatement statement = connection.prepareStatement(sql)) { @@ -300,9 +307,12 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements statement.setBoolean(14, applicationReleaseDTO.getIsSharedWithAllTenants()); statement.setString(15, applicationReleaseDTO.getMetaData()); statement.setString(16, applicationReleaseDTO.getSupportedOsVersions()); - statement.setString(17, applicationReleaseDTO.getCurrentState().toUpperCase()); - statement.setInt(18, applicationReleaseDTO.getId()); - statement.setInt(19, tenantId); + + if (applicationReleaseDTO.getCurrentState() != null) { + statement.setString(x++, applicationReleaseDTO.getCurrentState().toUpperCase()); + } + statement.setInt(x++, applicationReleaseDTO.getId()); + statement.setInt(x++, tenantId); if (statement.executeUpdate() == 0) { return null; } @@ -550,4 +560,65 @@ public class GenericApplicationReleaseDAOImpl extends AbstractDAOImpl implements throw new ApplicationManagementDAOException(msg, e); } } + + @Override + public List getReleaseByPackages(List packages, int tenantId) throws + ApplicationManagementDAOException { + + String sql = "SELECT " + + "AR.ID AS RELEASE_ID, " + + "AR.DESCRIPTION AS RELEASE_DESCRIPTION, " + + "AR.VERSION AS RELEASE_VERSION, " + + "AR.UUID AS RELEASE_UUID, " + + "AR.RELEASE_TYPE AS RELEASE_TYPE, " + + "AR.INSTALLER_LOCATION AS AP_RELEASE_STORED_LOC, " + + "AR.ICON_LOCATION AS AP_RELEASE_ICON_LOC, " + + "AR.BANNER_LOCATION AS AP_RELEASE_BANNER_LOC, " + + "AR.SC_1_LOCATION AS AP_RELEASE_SC1, " + + "AR.SC_2_LOCATION AS AP_RELEASE_SC2, " + + "AR.SC_3_LOCATION AS AP_RELEASE_SC3, " + + "AR.APP_HASH_VALUE AS RELEASE_HASH_VALUE, " + + "AR.APP_PRICE AS RELEASE_PRICE, " + + "AR.APP_META_INFO AS RELEASE_META_INFO, " + + "AR.PACKAGE_NAME AS PACKAGE_NAME, " + + "AR.SUPPORTED_OS_VERSIONS AS RELEASE_SUP_OS_VERSIONS, " + + "AR.RATING AS RELEASE_RATING, " + + "AR.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + + "AR.RATED_USERS AS RATED_USER_COUNT " + + "FROM AP_APP_RELEASE AS AR " + + "WHERE AR.TENANT_ID = ? AND AR.PACKAGE_NAME IN ("; + + StringJoiner joiner = new StringJoiner(",", sql, ")"); + packages.stream().map(ignored -> "?").forEach(joiner::add); + sql = joiner.toString(); + + try { + Connection connection = this.getDBConnection(); + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setInt(1, tenantId); + for (int y = 0; y < packages.size(); y++) { + // y +2 because tenantId parameter is 1 and the counter is starting at o for y + statement.setString(y+2, packages.get(y)); + } + try (ResultSet resultSet = statement.executeQuery()) { + List releaseDTOs = new ArrayList<>(); + while (resultSet.next()) { + releaseDTOs.add(DAOUtil.constructAppReleaseDTO(resultSet)); + } + return releaseDTOs; + } + } + } catch (DBConnectionException e) { + String msg = "Database connection error occurred while trying to get application release details which has " + + "packages: " + String.join(", ", packages); + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = + "Error while getting application release details which has packages: " + String.join(", ", packages) + + " , while executing the query " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java index 6561bac37f..f75b604b97 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java @@ -176,13 +176,15 @@ public class ApplicationManagerImpl implements ApplicationManager { @Override public Application createPublicApp(PublicAppWrapper publicAppWrapper, ApplicationArtifact applicationArtifact) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + if (log.isDebugEnabled()) { log.debug("Public app creating request is received. App name: " + publicAppWrapper.getName() + " Device Type: " + publicAppWrapper.getDeviceType()); } String publicAppStorePath = ""; - if (DeviceTypes.ANDROID.toString().equals(publicAppWrapper.getDeviceType())) { + if (DeviceTypes.ANDROID.toString().toLowerCase().equals(publicAppWrapper.getDeviceType())) { publicAppStorePath = Constants.GOOGLE_PLAY_STORE_URL; } else if (DeviceTypes.IOS.toString().equals(publicAppWrapper.getDeviceType())) { publicAppStorePath = Constants.APPLE_STORE_URL; @@ -194,18 +196,59 @@ public class ApplicationManagerImpl implements ApplicationManager { applicationReleaseDTO.setInstallerName(appInstallerUrl); applicationReleaseDTO.setUuid(UUID.randomUUID().toString()); applicationReleaseDTO.setAppHashValue(DigestUtils.md5Hex(appInstallerUrl)); - //uploading application artifacts + + ConnectionManagerUtil.openDBConnection(); + List exitingRelease; try { - applicationDTO.getApplicationReleaseDTOs().clear(); - applicationDTO.getApplicationReleaseDTOs() - .add(addImageArtifacts(applicationReleaseDTO, applicationArtifact)); - } catch (ResourceManagementException e) { - String msg = "Error Occured when uploading artifacts of the public app: " + publicAppWrapper.getName(); - log.error(msg, e); + exitingRelease = applicationReleaseDAO.getReleaseByPackages(Arrays.asList(applicationReleaseDTO.getPackageName()) + , tenantId); + } catch (ApplicationManagementDAOException e) { + String msg = "Error Occured when fetching release: " + publicAppWrapper.getName(); + log.error(msg); throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); } - //insert application data into database - return addAppDataIntoDB(applicationDTO); + + if (exitingRelease != null && exitingRelease.size() > 0) { + applicationDTO.getApplicationReleaseDTOs().clear(); + applicationReleaseDTO.setUuid(exitingRelease.get(0).getUuid()); + applicationReleaseDTO.setCurrentState(exitingRelease.get(0).getCurrentState()); + + try { + applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact); + applicationDTO.getApplicationReleaseDTOs().add(applicationReleaseDTO); + ConnectionManagerUtil.beginDBTransaction(); + applicationReleaseDAO.updateRelease(applicationReleaseDTO, tenantId); + ConnectionManagerUtil.commitDBTransaction(); + return APIUtil.appDtoToAppResponse(applicationDTO); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred when updating public app: " + publicAppWrapper.getName(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ResourceManagementException e) { + String msg = "Error occurred when adding artifacts of release: " + publicAppWrapper.getName(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } else { + //uploading application artifacts + try { + applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact); + applicationDTO.getApplicationReleaseDTOs().clear(); + applicationDTO.getApplicationReleaseDTOs().add(applicationReleaseDTO); + } catch (ResourceManagementException e) { + String msg = "Error Occured when uploading artifacts of the public app: " + publicAppWrapper.getName(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + //insert application data into database + return addAppDataIntoDB(applicationDTO); + } + } @Override @@ -3115,4 +3158,24 @@ public class ApplicationManagerImpl implements ApplicationManager { ConnectionManagerUtil.closeDBConnection(); } } + + @Override + public List getReleaseByPackageNames(List packageIds) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + ConnectionManagerUtil.openDBConnection(); + return this.applicationReleaseDAO.getReleaseByPackages(packageIds, tenantId); + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the database connection for getting application for the " + + "packages"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while getting application data for packages"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java index be5cbbd913..7d7d18b896 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -17,9 +17,19 @@ package org.wso2.carbon.device.application.mgt.core.impl; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey; +import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.application.mgt.common.ApplicationInstallResponse; import org.wso2.carbon.device.application.mgt.common.ApplicationType; @@ -29,6 +39,7 @@ import org.wso2.carbon.device.application.mgt.common.SubAction; import org.wso2.carbon.device.application.mgt.common.SubscriptionType; import org.wso2.carbon.device.application.mgt.common.SubscribingDeviceIdHolder; import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO; +import org.wso2.carbon.device.application.mgt.common.dto.ApplicationPolicyDTO; import org.wso2.carbon.device.application.mgt.common.dto.DeviceSubscriptionDTO; import org.wso2.carbon.device.application.mgt.common.dto.ScheduledSubscriptionDTO; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; @@ -51,6 +62,7 @@ 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.Constants; import org.wso2.carbon.device.application.mgt.core.util.HelperUtil; +import org.wso2.carbon.device.application.mgt.core.util.OAuthUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.MDMAppConstants; @@ -65,13 +77,18 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.core.util.MDMAndroidOperationUtil; import org.wso2.carbon.device.mgt.core.util.MDMIOSOperationUtil; +import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; +import org.wso2.carbon.user.api.UserStoreException; +import javax.ws.rs.core.MediaType; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -377,8 +394,19 @@ public class SubscriptionManagerImpl implements SubscriptionManager { activityList.add(activity); } } else { - Activity activity = addAppOperationOnDevices(applicationDTO, deviceIdentifiers, deviceType, action); - activityList.add(activity); + if (applicationDTO.getType().equals(ApplicationType.PUBLIC.toString())) { + List categories = getApplicationCategories(applicationDTO.getId()); + if (categories.contains("GooglePlaySyncedApp")) { + ApplicationPolicyDTO applicationPolicyDTO = new ApplicationPolicyDTO(); + applicationPolicyDTO.setApplicationDTO(applicationDTO); + applicationPolicyDTO.setDeviceIdentifierList(deviceIdentifiers); + applicationPolicyDTO.setAction(action); + installEnrollmentApplications(applicationPolicyDTO); + } + } else { + Activity activity = addAppOperationOnDevices(applicationDTO, deviceIdentifiers, deviceType, action); + activityList.add(activity); + } } ApplicationInstallResponse applicationInstallResponse = new ApplicationInstallResponse(); applicationInstallResponse.setActivities(activityList); @@ -414,6 +442,22 @@ public class SubscriptionManagerImpl implements SubscriptionManager { return subscribingDeviceIdHolder; } + private List getApplicationCategories(int id) throws ApplicationManagementException { + List categories; + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + ConnectionManagerUtil.openDBConnection(); + categories = this.applicationDAO.getAppCategories(id, tenantId); + return categories; + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while getting categories for application : " + id; + log.error(msg, e); + throw new ApplicationManagementException(msg); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + private ApplicationDTO getApplicationDTO(String uuid) throws ApplicationManagementException { ApplicationDTO applicationDTO; int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); @@ -681,4 +725,55 @@ public class SubscriptionManagerImpl implements SubscriptionManager { throw new ApplicationManagementException(msg, e); } } + + public int installEnrollmentApplications(ApplicationPolicyDTO applicationPolicyDTO) + throws ApplicationManagementException { + + HttpClient httpClient; + PostMethod request; + try { + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + ApiApplicationKey apiApplicationKey = OAuthUtils.getClientCredentials(tenantDomain); + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getRealmConfiguration().getAdminUserName() + Constants.ApplicationInstall.AT + tenantDomain; + AccessTokenInfo tokenInfo = OAuthUtils.getOAuthCredentials(apiApplicationKey, username); + String requestUrl = Constants.ApplicationInstall.ENROLLMENT_APP_INSTALL_PROTOCOL + + System.getProperty(Constants.ApplicationInstall.IOT_CORE_HOST) + + Constants.ApplicationInstall.COLON + + System.getProperty(Constants.ApplicationInstall.IOT_CORE_PORT) + + Constants.ApplicationInstall.GOOGLE_APP_INSTALL_URL; + Gson gson = new Gson(); + String payload = gson.toJson(applicationPolicyDTO); + + StringRequestEntity requestEntity = new StringRequestEntity(payload, MediaType.APPLICATION_JSON + , Constants.ApplicationInstall.ENCODING);; + httpClient = new HttpClient(); + request = new PostMethod(requestUrl); + request.addRequestHeader(Constants.ApplicationInstall.AUTHORIZATION + , Constants.ApplicationInstall.AUTHORIZATION_HEADER_VALUE + tokenInfo.getAccessToken()); + request.setRequestEntity(requestEntity); + httpClient.executeMethod(request); + return request.getStatusCode(); + + } catch (UserStoreException e) { + String msg = "Error while accessing user store for user with Android device."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (APIManagerException e) { + String msg = "Error while retrieving access token for Android device" ; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (HttpException e) { + String msg = "Error while calling the app store to install enrollment app with id: " + + applicationPolicyDTO.getApplicationDTO().getId() + + " on device"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (IOException e) { + String msg = "Error while installing the enrollment with id: " + applicationPolicyDTO.getApplicationDTO() + .getId() + " on device"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/APIUtil.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/APIUtil.java index f3b325caa2..2e4582aba7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/APIUtil.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/APIUtil.java @@ -356,6 +356,7 @@ public class APIUtil { applicationReleases.add(releaseDtoToRelease(applicationReleaseDTO)); } application.setApplicationReleases(applicationReleases); + application.setPackageName(applicationDTO.getPackageName()); return application; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java index 48939a36cb..68cdea9625 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/Constants.java @@ -115,4 +115,30 @@ public class Constants { public static final int REVIEW_PARENT_ID = -1; public static final int MAX_RATING = 5; + + public final class ApplicationInstall { + private ApplicationInstall() { + throw new AssertionError(); + } + + public static final String APPLICATION_NAME = "device_type_android"; + public static final String ENROLLMENT_APP_INSTALL_FEATURE_CODE = "ENROLLMENT_APP_INSTALL"; + public static final String DEFAULT_TOKEN_TYPE = "PRODUCTION"; + public static final String DEFAULT_VALIDITY_PERIOD = "3600"; + public static final String SUBSCRIPTION_SCOPE = "appm:subscribe"; + public static final String ENROLLMENT_APP_INSTALL_UUID = "uuid"; + public static final String GOOGLE_POLICY_PAYLOAD = "installGooglePolicyPayload"; + public static final String ENROLLMENT_APP_INSTALL_CODE = "enrollmentAppInstall"; + public static final String ENCODING = "UTF-8"; + public static final String AT = "@"; + public static final String DEVICE_TYPE_ANDROID = "android"; + public static final String COLON = ":"; + public static final String IOT_CORE_HOST = "iot.core.host"; + public static final String IOT_CORE_PORT = "iot.core.https.port"; + public static final String ENROLLMENT_APP_INSTALL_PROTOCOL = "https://"; + public static final String GOOGLE_APP_INSTALL_URL = "/api/device-mgt/android/v1.0/enterprise/change-app"; + + public static final String AUTHORIZATION = "Authorization"; + public static final String AUTHORIZATION_HEADER_VALUE = "Bearer "; + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/DAOUtil.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/DAOUtil.java index 00fb1e4cd6..041f041f57 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/DAOUtil.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/DAOUtil.java @@ -105,6 +105,7 @@ public class DAOUtil { application.setStatus(rs.getString("APP_STATUS")); application.setAppRating(rs.getDouble("APP_RATING")); application.setDeviceTypeId(rs.getInt("APP_DEVICE_TYPE_ID")); + application.setPackageName(rs.getString("PACKAGE_NAME")); application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs)); } else { if (application != null && application.getApplicationReleaseDTOs() != null) { diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/OAuthUtils.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/OAuthUtils.java new file mode 100644 index 0000000000..b57ffebeb7 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/util/OAuthUtils.java @@ -0,0 +1,90 @@ +/* + * 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.core.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; +import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey; +import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.application.mgt.common.dto.ApiRegistrationProfile; +import org.wso2.carbon.identity.jwt.client.extension.JWTClient; +import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; +import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; + +public class OAuthUtils { + + private static final Log log = LogFactory.getLog(OAuthUtils.class); + + public static ApiApplicationKey getClientCredentials(String tenantDomain) + throws UserStoreException, APIManagerException { + ApiRegistrationProfile registrationProfile = new ApiRegistrationProfile(); + registrationProfile.setApplicationName(Constants.ApplicationInstall.APPLICATION_NAME); + registrationProfile.setTags(new String[]{Constants.ApplicationInstall.DEVICE_TYPE_ANDROID}); + registrationProfile.setAllowedToAllDomains(false); + registrationProfile.setMappingAnExistingOAuthApp(false); + return getCredentials(registrationProfile, tenantDomain); + } + + public static ApiApplicationKey getCredentials(ApiRegistrationProfile registrationProfile, String tenantDomain) + throws UserStoreException, APIManagerException { + ApiApplicationKey apiApplicationKeyInfo; + if (tenantDomain == null || tenantDomain.isEmpty()) { + tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; + } + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(PrivilegedCarbonContext. + getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration().getAdminUserName()); + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + APIManagementProviderService apiManagementProviderService = (APIManagementProviderService) ctx. + getOSGiService(APIManagementProviderService.class, null); + apiApplicationKeyInfo = apiManagementProviderService. + generateAndRetrieveApplicationKeys(registrationProfile.getApplicationName(), + registrationProfile.getTags(), Constants.ApplicationInstall.DEFAULT_TOKEN_TYPE, + registrationProfile.getApplicationName(), registrationProfile.isAllowedToAllDomains(), + Constants.ApplicationInstall.DEFAULT_VALIDITY_PERIOD); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + return apiApplicationKeyInfo; + } + + public static AccessTokenInfo getOAuthCredentials(ApiApplicationKey apiApplicationKey, String username) + throws APIManagerException { + try { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + JWTClientManagerService jwtClientManagerService = (JWTClientManagerService) ctx. + getOSGiService(JWTClientManagerService.class, null); + JWTClient jwtClient = jwtClientManagerService.getJWTClient(); + return jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(), apiApplicationKey.getConsumerSecret(), + username, Constants.ApplicationInstall.SUBSCRIPTION_SCOPE); + } catch (JWTClientException e) { + String errorMsg = "Error while generating an OAuth token for user " + username; + log.error(errorMsg, e); + throw new APIManagerException(errorMsg, e); + } + } + +} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json index 56b1ae82d2..cdac823d7a 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json @@ -10,13 +10,16 @@ }, "license": "Apache License 2.0", "dependencies": { + "@ant-design/dark-theme": "^0.2.2", "@babel/polyfill": "^7.6.0", "acorn": "^6.2.0", - "antd": "^3.20.1", + "antd": "^3.22.2", "axios": "^0.19.0", "d3": "^5.9.7", "dagre": "^0.8.4", "fetch": "^1.1.0", + "gapi": "0.0.3", + "gapi-client": "0.0.3", "keymirror": "^0.1.1", "rc-tween-one": "^2.4.1", "react-d3-graph": "^2.1.0", @@ -54,7 +57,7 @@ "html-webpack-plugin": "^3.2.0", "img-loader": "^3.0.1", "json-loader": "^0.5.7", - "less": "^3.9.0", + "less": "^3.10.3", "less-loader": "^4.1.0", "mini-css-extract-plugin": "^0.5.0", "mocha": "^5.2.0", @@ -73,8 +76,8 @@ "sass-loader": "^6.0.7", "style-loader": "^0.18.2", "url-loader": "^1.1.2", - "webpack": "^4.35.2", - "webpack-cli": "^3.3.5", + "webpack": "^4.39.3", + "webpack-cli": "^3.3.7", "webpack-dev-server": "^3.7.2" }, "scripts": { diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json index 21457feb39..88d68e9e8d 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json @@ -1,14 +1,9 @@ { "theme": { - "type": "default", - "value": "lightBaseTheme", "logo": "https://entgra.io/assets/images/svg/logo.svg", - "primaryColor": "rgb(24, 144, 255)" + "primaryColor": "#badc58" }, "serverConfig": { - "protocol": "https", - "hostname": "localhost", - "httpsPort": "9443", "invoker": { "uri": "/publisher-ui-request-handler/invoke", "publisher": "/application-mgt-publisher/v1.0", diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/App.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/App.js index 88c8968658..484fe6be6c 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/App.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/App.js @@ -67,18 +67,37 @@ class App extends React.Component { axios.get( window.location.origin + "/publisher/public/conf/config.json", ).then(res => { - console.log(res); + const config = res.data; + + this.getAndroidEnterpriseToken(config); + + }).catch((error) => { this.setState({ loading: false, - config: res.data + error: true }) + }); + } + + getAndroidEnterpriseToken = (config) => { + axios.get( + window.location.origin + config.serverConfig.invoker.uri + "/device-mgt/android/v1.0/enterprise/store-url?approveApps=true" + + "&searchEnabled=true&isPrivateAppsEnabled=true&isWebAppEnabled=true&isOrganizeAppPageVisible=true&isManagedConfigEnabled=true" + + "&host=https://localhost:9443", + ).then(res => { + config.androidEnterpriseToken = res.data.data.token; + this.setState({ + loading: false, + config: config + }); }).catch((error) => { + config.androidEnterpriseToken = null; this.setState({ loading: false, - error: true + config: config }) }); - } + }; render() { const {loading, error} = this.state; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js index 1a1b9a2611..12cf8cb591 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js @@ -40,6 +40,8 @@ import ReactHtmlParser from 'react-html-parser'; import "./AppDetailsDrawer.css"; import pSBC from "shade-blend-color"; import {withConfigContext} from "../../../../context/ConfigContext"; +import ManagedConfigurationsIframe + from "../../../manage/android-enterprise/ManagedConfigurationsIframe/ManagedConfigurationsIframe"; const {Meta} = Card; const {Text, Title} = Typography; @@ -474,6 +476,31 @@ class AppDetailsDrawer extends React.Component { + {/*display manage config button only if the app is public android app*/} + {(app.type === "PUBLIC") && (app.deviceType === "android") && ( +
+
+ Set up managed configurations +
+
+ + If you are developing apps for the enterprise market, you may need to satisfy + particular requirements set by a organization's policies. Managed + configurations, + previously known as application restrictions, allow the organization's IT admin + to + remotely specify settings for apps. This capability is particularly useful for + organization-approved apps deployed to a work profile. + +
+
+ + +
+ )} + Releases {/*display add new release only if app type is enterprise*/} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js index d84ec2145e..9ad5f239f0 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js @@ -224,7 +224,7 @@ class EditReleaseModal extends React.Component { isSharedWithAllTenants, metaData: JSON.stringify(this.state.metaData), releaseType: releaseType, - supportedOsVersions: "4.0-10.0" + supportedOsVersions: "4-30" }; if (specificElements.hasOwnProperty("binaryFile") && binaryFiles.length === 1) { diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/AddNewPage/AddNewPage.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/AddNewPage/AddNewPage.js new file mode 100644 index 0000000000..29a636d293 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/AddNewPage/AddNewPage.js @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import {Button, Divider, Form, Input, message, Modal, notification, Spin} from "antd"; +import axios from "axios"; +import {withConfigContext} from "../../../../context/ConfigContext"; +import {withRouter} from "react-router"; +import {handleApiError} from "../../../../js/Utils"; + +class AddNewPage extends React.Component { + + state = { + visible: false, + pageName: '' + }; + + showModal = () => { + this.setState({ + visible: true, + loading: false + }); + }; + + + handleCancel = e => { + console.log(e); + this.setState({ + visible: false, + }); + }; + + handlePageName = (e) => { + this.setState({ + pageName: e.target.value, + }); + }; + + createNewPage = () => { + const config = this.props.context; + this.setState({loading: true}); + + axios.post( + window.location.origin + config.serverConfig.invoker.uri + + "/device-mgt/android/v1.0/enterprise/store-layout/page", + { + "locale": "en", + "pageName": this.state.pageName + } + ).then(res => { + if (res.status === 200) { + + const {pageId, pageName} = res.data.data; + + notification["success"]({ + message: 'Saved!', + description: 'Page created successfully!' + }); + + this.setState({loading: false}); + + this.props.history.push(`/publisher/manage/android-enterprise/pages/${pageName}/${pageId}`); + } + }).catch((error) => { + handleApiError(error, "Error occurred while trying to update the cluster."); + this.setState({loading: false}); + }); + }; + + render() { + return ( +
+ + + +

Choose a name for the page

+ + +
+ + + +
+
+
+
+ ); + } +} + +export default withConfigContext(withRouter(AddNewPage)); \ No newline at end of file diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/GooglePlayIframe.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/GooglePlayIframe.js new file mode 100644 index 0000000000..7460de2796 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/android-enterprise/GooglePlayIframe.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from "react"; +import {Modal, Button} from "antd"; +import {withConfigContext} from "../../../context/ConfigContext"; + +class GooglePlayIframe extends React.Component { + constructor(props) { + super(props); + this.config = this.props.context; + + this.state = { + visible: false + }; + } + + showModal = () => { + this.setState({ + visible: true, + }); + }; + + handleOk = e => { + console.log(e); + this.setState({ + visible: false, + }); + }; + + handleCancel = e => { + console.log(e); + this.setState({ + visible: false, + }); + }; + + render() { + return ( +
+ + +