Enrollment application install feature for policy

revert-dabc3590
Saad Sahibjan 6 years ago committed by Dharmakeerthi Lasantha
parent f7cb8e50b1
commit 8355861083

@ -354,5 +354,10 @@
<groupId>org.codehaus.jackson</groupId> <groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId> <artifactId>jackson-core-asl</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -0,0 +1,59 @@
/*
* Copyright (c) 2018, 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.mdm.services.android.bean;
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;
}
}

@ -15,6 +15,22 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
* *
*
* Copyright (c) 2018, 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.mdm.services.android.services.impl; package org.wso2.carbon.mdm.services.android.services.impl;
@ -31,6 +47,8 @@ import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature;
import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.PolicyComplianceException; import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.PolicyComplianceException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager;
@ -263,7 +281,20 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
operation, deviceIdentifiers); operation, deviceIdentifiers);
} }
PolicyManagerService policyManagerService = AndroidAPIUtils.getPolicyManagerService(); PolicyManagerService policyManagerService = AndroidAPIUtils.getPolicyManagerService();
policyManagerService.getEffectivePolicy(new DeviceIdentifier(androidDevice.getDeviceIdentifier(), device.getType())); Policy effectivePolicy = policyManagerService.
getEffectivePolicy(new DeviceIdentifier(androidDevice.getDeviceIdentifier(), device.getType()));
if (effectivePolicy != null) {
List<ProfileFeature> effectiveProfileFeatures = effectivePolicy.getProfile().
getProfileFeaturesList();
for (ProfileFeature feature : effectiveProfileFeatures) {
if (AndroidConstants.ApplicationInstall.ENROLLMENT_APP_INSTALL_FEATURE_CODE
.equals(feature.getFeatureCode())) {
AndroidDeviceUtils.installEnrollmentApplications(feature, deviceIdentifier.getId());
break;
}
}
}
Message responseMessage = new Message(); Message responseMessage = new Message();
responseMessage.setResponseCode(Response.Status.OK.toString()); responseMessage.setResponseCode(Response.Status.OK.toString());

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*
* Copyright (c) 2018, 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.mdm.services.android.util; package org.wso2.carbon.mdm.services.android.util;
@ -139,6 +156,29 @@ public final class AndroidConstants {
public static final String IS_ACTIVE = "isActive"; public static final String IS_ACTIVE = "isActive";
} }
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_ID = "appId";
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 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 ENROLLMENT_APP_INSTALL_CONTEXT = "/api/appm/store/v1.1/apps/mobile/schedule-install";
public static final String AUTHORIZATION = "Authorization";
public static final String AUTHORIZATION_HEADER_VALUE = "Bearer ";
}
public final class ErrorMessages { public final class ErrorMessages {
private ErrorMessages () { throw new AssertionError(); } private ErrorMessages () { throw new AssertionError(); }

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*
* Copyright (c) 2018, 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.mdm.services.android.util; package org.wso2.carbon.mdm.services.android.util;
@ -24,6 +41,10 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonNull; import com.google.gson.JsonNull;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; 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.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.analytics.api.AnalyticsDataAPI; import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
@ -32,6 +53,8 @@ import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry; import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
import org.wso2.carbon.analytics.datasource.commons.Record; import org.wso2.carbon.analytics.datasource.commons.Record;
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException; import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
@ -47,17 +70,23 @@ import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature;
import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.ComplianceFeature; import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.ComplianceFeature;
import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.PolicyComplianceException; import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.PolicyComplianceException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager;
import org.wso2.carbon.device.mgt.core.search.mgt.impl.Utils; import org.wso2.carbon.device.mgt.core.search.mgt.impl.Utils;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.mdm.services.android.bean.DeviceState; import org.wso2.carbon.mdm.services.android.bean.DeviceState;
import org.wso2.carbon.mdm.services.android.bean.ErrorListItem; import org.wso2.carbon.mdm.services.android.bean.ErrorListItem;
import org.wso2.carbon.mdm.services.android.bean.ErrorResponse; import org.wso2.carbon.mdm.services.android.bean.ErrorResponse;
import org.wso2.carbon.mdm.services.android.exception.BadRequestException; import org.wso2.carbon.mdm.services.android.exception.BadRequestException;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.user.api.UserStoreException;
import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolation;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -460,4 +489,54 @@ public class AndroidDeviceUtils {
return errorResponse; return errorResponse;
} }
public static void installEnrollmentApplications(ProfileFeature feature, String deviceId)
throws PolicyManagementException {
String appId = "";
String payload;
StringRequestEntity requestEntity;
HttpClient httpClient;
PostMethod request;
try {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
ApiApplicationKey apiApplicationKey = OAuthUtils.getClientCredentials(tenantDomain);
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName() + AndroidConstants.ApplicationInstall.AT + tenantDomain;
AccessTokenInfo tokenInfo = OAuthUtils.getOAuthCredentials(apiApplicationKey, username);
String requestUrl = AndroidConstants.ApplicationInstall.ENROLLMENT_APP_INSTALL_PROTOCOL +
System.getProperty(AndroidConstants.ApplicationInstall.IOT_CORE_HOST) +
AndroidConstants.ApplicationInstall.COLON +
System.getProperty(AndroidConstants.ApplicationInstall.IOT_CORE_PORT) +
AndroidConstants.ApplicationInstall.ENROLLMENT_APP_INSTALL_CONTEXT;
JsonElement appListElement = new JsonParser().parse(feature.getContent().toString()).getAsJsonObject()
.get(AndroidConstants.ApplicationInstall.ENROLLMENT_APP_INSTALL_CODE);
JsonArray appListArray = appListElement.getAsJsonArray();
for (JsonElement appElement : appListArray) {
appId = appElement.getAsJsonObject().
get(AndroidConstants.ApplicationInstall.ENROLLMENT_APP_INSTALL_ID).getAsString();
payload = "{\"appId\": \"" + appId + "\", \"scheduleTime\":\"2013-12-25T15:25:30-05:00\"," +
"\"deviceIds\": [\"{\\\"id\\\":\\\"" + deviceId + "\\\", \\\"type\\\":\\\"android\\\"}\"]}";
requestEntity = new StringRequestEntity(payload, MediaType.APPLICATION_JSON,
AndroidConstants.ApplicationInstall.ENCODING);
httpClient = new HttpClient();
request = new PostMethod(requestUrl);
request.addRequestHeader(AndroidConstants.ApplicationInstall.AUTHORIZATION,
AndroidConstants.ApplicationInstall.AUTHORIZATION_HEADER_VALUE + tokenInfo.getAccessToken());
request.setRequestEntity(requestEntity);
httpClient.executeMethod(request);
}
} catch (UserStoreException e) {
throw new PolicyManagementException("Error while accessing user store for user with iOS device id: " +
deviceId, e);
} catch (APIManagerException e) {
throw new PolicyManagementException("Error while retrieving access token for Android device id: " +
deviceId, e);
} catch (HttpException e) {
throw new PolicyManagementException("Error while calling the app store to install enrollment app with " +
"id: " + appId + " on device with id: " + deviceId, e);
} catch (IOException e) {
throw new PolicyManagementException("Error while installing the enrollment app with id: " + appId +
" on device with id: " + deviceId, e);
}
}
} }

@ -0,0 +1,90 @@
/*
* Copyright (c) 2018, 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.mdm.services.android.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.mdm.services.android.bean.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(AndroidConstants.ApplicationInstall.APPLICATION_NAME);
registrationProfile.setTags(new String[]{AndroidConstants.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(), AndroidConstants.ApplicationInstall.DEFAULT_TOKEN_TYPE,
registrationProfile.getApplicationName(), registrationProfile.isAllowedToAllDomains(),
AndroidConstants.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, AndroidConstants.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);
}
}
}

@ -14,6 +14,23 @@
* either express or implied. See the License for the * either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*
* Copyright (c) 2018, 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.
*/ */
var androidOperationModule = function () { var androidOperationModule = function () {
@ -79,7 +96,9 @@ var androidOperationModule = function () {
"RUNTIME_PERMISSION_POLICY_OPERATION": "runtime-permission-policy", "RUNTIME_PERMISSION_POLICY_OPERATION": "runtime-permission-policy",
"RUNTIME_PERMISSION_POLICY_OPERATION_CODE": "RUNTIME_PERMISSION_POLICY", "RUNTIME_PERMISSION_POLICY_OPERATION_CODE": "RUNTIME_PERMISSION_POLICY",
"COSU_PROFILE_CONFIGURATION_OPERATION": "cosu-profile-configuration", "COSU_PROFILE_CONFIGURATION_OPERATION": "cosu-profile-configuration",
"COSU_PROFILE_CONFIGURATION_OPERATION_CODE": "COSU_PROFILE" "COSU_PROFILE_CONFIGURATION_OPERATION_CODE": "COSU_PROFILE",
"ENROLLMENT_APP_INSTALL": "enrollment-app-install",
"ENROLLMENT_APP_INSTALL_CODE": "ENROLLMENT_APP_INSTALL"
}; };
/** /**
@ -177,6 +196,11 @@ var androidOperationModule = function () {
"cosuWhitelistedApplications": operationPayload["whitelistedApplications"] "cosuWhitelistedApplications": operationPayload["whitelistedApplications"]
}; };
break; break;
case androidOperationConstants["ENROLLMENT_APP_INSTALL_CODE"]:
payload = {
"enrollmentAppInstall": operationPayload["enrollmentAppInstall"]
};
break;
} }
return payload; return payload;
}; };
@ -384,6 +408,14 @@ var androidOperationModule = function () {
} }
}; };
break; break;
case androidOperationConstants["ENROLLMENT_APP_INSTALL_CODE"]:
operationType = operationTypeConstants["PROFILE"];
payload = {
"operation": {
"enrollmentAppInstall": operationData["enrollmentAppInstall"]
}
};
break;
default: default:
// If the operation is neither of above, it is a command operation // If the operation is neither of above, it is a command operation
operationType = operationTypeConstants["COMMAND"]; operationType = operationTypeConstants["COMMAND"];
@ -708,6 +740,27 @@ var androidOperationModule = function () {
} else if (operationDataObj.hasClass("multi-column-key-value-pair-array")) { } else if (operationDataObj.hasClass("multi-column-key-value-pair-array")) {
// generating input fields to populate complex value // generating input fields to populate complex value
if (value) { if (value) {
if (operationDataObj.hasClass("specific-enrollment-app-install")) {
if ($(".enrollment-app-install-input", this).length > 0) {
for (i=0; i<value.length; i++) {
$(".enrollment-app-install-input", this).each(function() {
childInput = $(this);
var childInputKey = childInput.data("child-key");
if (childInputKey === "appId" && value[i].appId === childInput.val()) {
childInput.parent().find("a").filterByData("click-event", "add-enrollment-app").click();
}
});
}
} else {
$('[data-add-form-container="#enrollment-app-install-grid"]').empty();
for (i=0; i<value.length; i++) {
var content = '<tr><td data-title="enrollment-app-install-app-name">'
+ value[i].appName + '</td><td data-title="enrollment-app-install-version">'
+ value[i].version + '</td></tr>';
$('[data-add-form-container="#enrollment-app-install-grid"]').append(content);
}
}
} else {
for (i = 0; i < value.length; ++i) { for (i = 0; i < value.length; ++i) {
operationDataObj.parent().find("a").filterByData("click-event", "add-form").click(); operationDataObj.parent().find("a").filterByData("click-event", "add-form").click();
} }
@ -739,6 +792,7 @@ var androidOperationModule = function () {
} }
} }
} }
}
// only for app whitelisting and black listing // only for app whitelisting and black listing
if (operationCode == "APP-RESTRICTION" && key == "restrictedApplications") { if (operationCode == "APP-RESTRICTION" && key == "restrictedApplications") {

@ -14,6 +14,23 @@
* either express or implied. See the License for the * either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*
* Copyright (c) 2018, 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.
*/ */
var configuredOperations = []; var configuredOperations = [];
@ -37,7 +54,9 @@ var androidOperationConstants = {
"RUNTIME_PERMISSION_POLICY_OPERATION_CODE": "RUNTIME_PERMISSION_POLICY", "RUNTIME_PERMISSION_POLICY_OPERATION_CODE": "RUNTIME_PERMISSION_POLICY",
"RUNTIME_PERMISSION_POLICY_OPERATION": "runtime-permission-policy", "RUNTIME_PERMISSION_POLICY_OPERATION": "runtime-permission-policy",
"COSU_PROFILE_CONFIGURATION_OPERATION": "cosu-profile-configuration", "COSU_PROFILE_CONFIGURATION_OPERATION": "cosu-profile-configuration",
"COSU_PROFILE_CONFIGURATION_OPERATION_CODE": "COSU_PROFILE" "COSU_PROFILE_CONFIGURATION_OPERATION_CODE": "COSU_PROFILE",
"ENROLLMENT_APP_INSTALL": "enrollment-app-install",
"ENROLLMENT_APP_INSTALL_CODE": "ENROLLMENT_APP_INSTALL"
}; };
/** /**
@ -537,6 +556,24 @@ var validatePolicyProfile = function () {
// Updating validationStatusArray with validationStatus // Updating validationStatusArray with validationStatus
validationStatusArray.push(validationStatus); validationStatusArray.push(validationStatus);
} }
if ($.inArray(androidOperationConstants["ENROLLMENT_APP_INSTALL_CODE"], configuredOperations) != -1) {
//If enrollment app install configured
operation = androidOperationConstants["ENROLLMENT_APP_INSTALL"];
var enrollmentAppInstallAppList = "div#install-app-enrollment .child-input";
if($(enrollmentAppInstallAppList).length == 0) {
validationStatus = {
"error": true,
"subErrorMsg": "Applications are not selected to be installed during device enrollment.",
"erroneousFeature": operation
};
} else {
validationStatus = {
"error": false,
"okFeature": operation
};
}
validationStatusArray.push(validationStatus);
}
} }
// ending validation process // ending validation process
@ -771,6 +808,13 @@ var showHideHelpText = function (addFormContainer) {
} }
}; };
var applyDataTable = function() {
$("#enrollment-app-install-table").datatables_extended({
ordering: false,
lengthMenu: [5, 10, 25, 50, 100]
});
};
$(document).ready(function () { $(document).ready(function () {
// Maintains an array of configured features of the profile // Maintains an array of configured features of the profile
var advanceOperations = ".wr-advance-operations"; var advanceOperations = ".wr-advance-operations";
@ -945,4 +989,22 @@ $(document).ready(function () {
setId(addFormContainer); setId(addFormContainer);
showHideHelpText(addFormContainer); showHideHelpText(addFormContainer);
}); });
// add app entry for enrollment-app-install
$(advanceOperations).on("click", "[data-click-event=add-enrollment-app]", function () {
$(this).attr("hidden", true);
$(this).siblings("a").removeAttr("hidden");
$(this).parent().parent().find("input").each(function () {
$(this).addClass("child-input");
});
});
// remove app entry for enrollment-app-install
$(advanceOperations).on("click", "[data-click-event=remove-enrollment-app]", function () {
$(this).attr("hidden", true);
$(this).siblings("a").removeAttr("hidden");
$(this).parent().parent().find("input").each(function () {
$(this).removeClass("child-input");
});
});
}); });

@ -132,6 +132,16 @@
class="fw fw-error"></i></span> class="fw fw-error"></i></span>
</a> </a>
{{/unless}} {{/unless}}
<a href="javascript:void(0)" onclick="showAdvanceOperation('enrollment-app-install', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-application fw-stack-2x"></i>
</span>
Enrollment Application Install
<span id="enrollment-app-install-configured" class="has-configured status-icon hidden"><i
class="fw fw-success"></i></span>
<span id="enrollment-app-install-ok" class="has-success status-icon hidden"><i class="fw fw-success"></i></span>
<span id="enrollment-app-install-error" class="has-error status-icon hidden"><i class="fw fw-error"></i></span>
</a>
</div> </div>
<div class="wr-hidden-operations-content col-lg-8"> <div class="wr-hidden-operations-content col-lg-8">
@ -1799,5 +1809,90 @@
</div> </div>
</div> </div>
</div> </div>
<!--enrolment-app-install-->
<div class="wr-hidden-operation" data-operation="enrollment-app-install">
<div class="panel panel-default operation-data" data-operation="enrollment-app-install"
data-operation-code="ENROLLMENT_APP_INSTALL">
<div id="enrollment-app-install-heading" class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
Enrollment Application Install
<label class="wr-input-control switch" data-toggle="collapse"
data-target="#enrollment-app-install-body">
<input type="checkbox"/>
<span class="helper"></span>
<span class="text"></span>
</label>
</h2>
<div class="panel-title-description">
This configuration can be used to install applications during Android device enrollment.
<div class="message message-info">
<i class="icon fw fw-info"></i>
This configuration will be applied <b>only during Android device enrollment</b>.
</div>
</div>
</div>
<div id="enrollment-app-install-body" class="panel-collapse panel-body collapse" role="tabpanel"
aria-labelledby="enrollment-app-install-body">
<hr/>
<div id="enrollment-app-install-feature-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<label class="wr-input-label">
Select Enrollment Applications
</label>
<div id="install-app-enrollment"
class="operationDataKeys grouped-array-input multi-column-key-value-pair-array specific-enrollment-app-install"
data-key="enrollmentAppInstall" data-column-count="4">
<table class="table table-responsive table-striped data-table" id="enrollment-app-install-table">
<thead>
<tr class="sort-row">
<th>Application Name</th>
<th>Version</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each storeapps}}
<tr data-add-form-container="#enrollment-app-install-grid">
<td data-title="enrollment-app-install-app-name">
{{this.appName}}
<input class="enrollment-app-install-input" type="hidden" data-child-key="appName" value="{{this.appName}}"/>
</td>
<td data-title="enrollment-app-install-app-name">
{{this.version}}
<input class="enrollment-app-install-input" type="hidden" data-child-key="version" value="{{this.version}}"/>
</td>
<td data-title="enrollment-app-install-app-selection">
<input class="enrollment-app-install-input" type="hidden" data-child-key="packageName" value="{{this.packageName}}"/>
<input class="enrollment-app-install-input" type="hidden" data-child-key="appId" value="{{this.appId}}"/>
<a href="#enrollment-app-install-grid" data-click-event="add-enrollment-app">
<span>
<i class="fa fa-plus-circle fa-2x"></i>
</span>
</a>
<a href="#enrollment-app-install-grid" data-click-event="remove-enrollment-app" hidden>
<span>
<i class="fa fa-minus-circle fa-2x"></i>
</span>
</a>
</td>
</tr>
{{else}}
<tr>
<td>No android apps available in the store.</td>
<td></td>
<td></td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
</div>
<!--/enrolment-app-install-->
</div> </div>
<script type="text/javascript">applyDataTable();</script>
</div> </div>

@ -198,6 +198,13 @@ var changeAndroidWifiPolicyEAP = function (select, superSelect) {
} }
}; };
var applyDataTable = function() {
$("#enrollment-app-install-table").datatables_extended({
ordering: false,
lengthMenu: [5, 10, 25, 50, 100]
});
};
$(document).ready(function () { $(document).ready(function () {
var advanceOperations = ".wr-advance-operations"; var advanceOperations = ".wr-advance-operations";
$(advanceOperations).on("click", ".wr-input-control.switch", function (event) { $(advanceOperations).on("click", ".wr-input-control.switch", function (event) {

@ -114,6 +114,16 @@
class="fw fw-error"></i></span> class="fw fw-error"></i></span>
</a> </a>
{{/unless}} {{/unless}}
<a href="javascript:void(0)" onclick="showAdvanceOperation('enrollment-app-install', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-application fw-stack-2x"></i>
</span>
Enrollment Application Install
<span id="enrollment-app-install-configured" class="has-configured status-icon hidden"><i
class="fw fw-success"></i></span>
<span id="enrollment-app-install-ok" class="has-success status-icon hidden"><i class="fw fw-success"></i></span>
<span id="enrollment-app-install-error" class="has-error status-icon hidden"><i class="fw fw-error"></i></span>
</a>
</div> </div>
<div class="wr-hidden-operations-content col-lg-8"> <div class="wr-hidden-operations-content col-lg-8">
<!-- passcode-policy --> <!-- passcode-policy -->
@ -1909,5 +1919,57 @@
</div> </div>
</div> </div>
</div> </div>
<!--enrolment-app-install-->
<div class="wr-hidden-operation" data-operation="enrollment-app-install">
<div class="panel panel-default operation-data" data-operation="enrollment-app-install"
data-operation-code="ENROLLMENT_APP_INSTALL">
<div id="enrollment-app-install-heading" class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
Enrollment Application Install
<label class="wr-input-control switch hidden" data-toggle="collapse"
data-target="#enrollment-app-install-body">
<input type="checkbox"/>
<span class="helper"></span>
<span class="text"></span>
</label>
</h2>
<div class="panel-title-description">
This configuration can be used to install applications during Android device enrollment.
<div class="message message-info">
<i class="icon fw fw-info"></i>
This configuration will be applied <b>only during Android device enrollment</b>.
</div>
</div>
</div>
<div id="enrollment-app-install-body" class="panel-collapse panel-body collapse" role="tabpanel"
aria-labelledby="enrollment-app-install-body">
<hr/>
<div id="enrollment-app-install-feature-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<label class="wr-input-label">
Selected Enrollment Applications
</label>
<div id="install-app-enrollment"
class="operationDataKeys grouped-array-input multi-column-key-value-pair-array specific-enrollment-app-install"
data-key="enrollmentAppInstall" data-column-count="4">
<table class="table table-responsive table-striped" id="enrollment-app-install-table">
<thead>
<tr class="sort-row">
<th>Application Name</th>
<th>Version</th>
</tr>
</thead>
<tbody data-add-form-container="#enrollment-app-install-grid">
</tbody>
</table>
</div>
</div>
</div>
</div>
<!--/enrolment-app-install-->
</div> </div>
<script type="text/javascript">applyDataTable();</script>
</div> </div>

@ -14,6 +14,23 @@
* either express or implied. See the License for the * either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*
* Copyright (c) 2018, 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.
*/ */
var configuredOperations = []; var configuredOperations = [];
@ -32,7 +49,9 @@ var androidOperationConstants = {
"APPLICATION_OPERATION": "app-restriction", "APPLICATION_OPERATION": "app-restriction",
"APPLICATION_OPERATION_CODE": "APP-RESTRICTION", "APPLICATION_OPERATION_CODE": "APP-RESTRICTION",
"KIOSK_APPS_CODE": "KIOSK_APPS", "KIOSK_APPS_CODE": "KIOSK_APPS",
"KIOSK_APPS": "cosu-whitelisted-applications" "KIOSK_APPS": "cosu-whitelisted-applications",
"ENROLLMENT_APP_INSTALL": "enrollment-app-install",
"ENROLLMENT_APP_INSTALL_CODE": "ENROLLMENT_APP_INSTALL"
}; };
/** /**
@ -456,6 +475,24 @@ var validatePolicyProfile = function () {
// Updating validationStatusArray with validationStatus // Updating validationStatusArray with validationStatus
validationStatusArray.push(validationStatus); validationStatusArray.push(validationStatus);
} }
if ($.inArray(androidOperationConstants["ENROLLMENT_APP_INSTALL_CODE"], configuredOperations) != -1) {
//If enrollment app install configured
operation = androidOperationConstants["ENROLLMENT_APP_INSTALL"];
var enrollmentAppInstallAppList = "div#install-app-enrollment .child-input";
if($(enrollmentAppInstallAppList).length == 0) {
validationStatus = {
"error": true,
"subErrorMsg": "Applications are not selected to be installed during device enrollment.",
"erroneousFeature": operation
};
} else {
validationStatus = {
"error": false,
"okFeature": operation
};
}
validationStatusArray.push(validationStatus);
}
} }
// ending validation process // ending validation process
@ -733,6 +770,13 @@ var showHideHelpText = function (addFormContainer) {
} }
}; };
var applyDataTable = function() {
$("#enrollment-app-install-table").datatables_extended({
ordering: false,
lengthMenu: [5, 10, 25, 50, 100]
});
};
$(document).ready(function () { $(document).ready(function () {
// Maintains an array of configured features of the profile // Maintains an array of configured features of the profile
var advanceOperations = ".wr-advance-operations"; var advanceOperations = ".wr-advance-operations";
@ -907,4 +951,22 @@ $(document).ready(function () {
setId(addFormContainer); setId(addFormContainer);
showHideHelpText(addFormContainer); showHideHelpText(addFormContainer);
}); });
// add app entry for enrollment-app-install
$(advanceOperations).on("click", "[data-click-event=add-enrollment-app]", function () {
$(this).attr("hidden", true);
$(this).siblings("a").removeAttr("hidden");
$(this).parent().parent().find("input").each(function () {
$(this).addClass("child-input");
});
});
// remove app entry for enrollment-app-install
$(advanceOperations).on("click", "[data-click-event=remove-enrollment-app]", function () {
$(this).attr("hidden", true);
$(this).siblings("a").removeAttr("hidden");
$(this).parent().parent().find("input").each(function () {
$(this).removeClass("child-input");
});
});
}); });

@ -140,6 +140,16 @@
class="fw fw-error"></i></span> class="fw fw-error"></i></span>
</a> </a>
{{/unless}} {{/unless}}
<a href="javascript:void(0)" onclick="showAdvanceOperation('enrollment-app-install', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-application fw-stack-2x"></i>
</span>
Enrollment Application Install
<span id="enrollment-app-install-configured" class="has-configured status-icon hidden"><i
class="fw fw-success"></i></span>
<span id="enrollment-app-install-ok" class="has-success status-icon hidden"><i class="fw fw-success"></i></span>
<span id="enrollment-app-install-error" class="has-error status-icon hidden"><i class="fw fw-error"></i></span>
</a>
</div> </div>
<div class="wr-hidden-operations-content col-lg-8"> <div class="wr-hidden-operations-content col-lg-8">
@ -1827,5 +1837,91 @@
</div> </div>
</div> </div>
</div> </div>
<!--enrolment-app-install-->
<div class="wr-hidden-operation" data-operation="enrollment-app-install">
<div class="panel panel-default operation-data" data-operation="enrollment-app-install"
data-operation-code="ENROLLMENT_APP_INSTALL">
<div id="enrollment-app-install-heading" class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
Enrollment Application Install
<label class="wr-input-control switch" data-toggle="collapse"
data-target="#enrollment-app-install-body">
<input type="checkbox"/>
<span class="helper"></span>
<span class="text"></span>
</label>
</h2>
<div class="panel-title-description">
Enforce applications to be installed during Android device enrollment.
<div class="message message-info">
<i class="icon fw fw-info"></i>
This configuration will be applied <b>only during Android device enrollment</b>.
</div>
</div>
</div>
<div id="enrollment-app-install-body" class="panel-collapse panel-body collapse" role="tabpanel"
aria-labelledby="enrollment-app-install-body">
<hr/>
<div id="enrollment-app-install-feature-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<label class="wr-input-label">
Select Enrollment Applications
</label>
<div id="install-app-enrollment"
class="operationDataKeys grouped-array-input multi-column-key-value-pair-array specific-enrollment-app-install"
data-key="enrollmentAppInstall" data-column-count="4">
<table class="table table-responsive table-striped data-table" id="enrollment-app-install-table">
<thead>
<tr class="sort-row">
<th>Application Name</th>
<th>Version</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each storeapps}}
<tr data-add-form-container="#enrollment-app-install-grid">
<td data-title="enrollment-app-install-app-name">
{{this.appName}}
<input class="enrollment-app-install-input" type="hidden" data-child-key="appName" value="{{this.appName}}"/>
</td>
<td data-title="enrollment-app-install-app-name">
{{this.version}}
<input class="enrollment-app-install-input" type="hidden" data-child-key="version" value="{{this.version}}"/>
</td>
<td data-title="enrollment-app-install-app-selection">
<input class="enrollment-app-install-input" type="hidden" data-child-key="packageName" value="{{this.packageName}}"/>
<input class="enrollment-app-install-input" type="hidden" data-child-key="appId" value="{{this.appId}}"/>
<a href="#enrollment-app-install-grid" data-click-event="add-enrollment-app">
<span>
<i class="fa fa-plus-circle fa-2x"></i>
</span>
</a>
<a href="#enrollment-app-install-grid" data-click-event="remove-enrollment-app" hidden>
<span>
<i class="fa fa-minus-circle fa-2x"></i>
</span>
</a>
</td>
</tr>
{{else}}
<tr>
<td>No android apps available in the store.</td>
<td></td>
<td></td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
</div>
<!--/enrolment-app-install-->
</div> </div>
<script type="text/javascript">applyDataTable();</script>
</div> </div>
Loading…
Cancel
Save