Add association apis

fixes https://roadmap.entgra.net/issues/10182
issue-10462/secure-pending-operation-6.2
inoshperera 1 year ago
parent 61ffd4abff
commit 54111b4d94

@ -0,0 +1,113 @@
/*
* Copyright (c) 2018 - 2023, 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 io.entgra.device.mgt.core.application.mgt.common.dto;
public class VppAssociationDTO {
int id;
String adamId;
String clientUserId;
String pricingParam;
String associationType;
int assetId;
int clientId;
int tenantId;
String createdTime;
String lastUpdatedTime;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAdamId() {
return adamId;
}
public void setAdamId(String adamId) {
this.adamId = adamId;
}
public String getClientUserId() {
return clientUserId;
}
public void setClientUserId(String clientUserId) {
this.clientUserId = clientUserId;
}
public String getPricingParam() {
return pricingParam;
}
public void setPricingParam(String pricingParam) {
this.pricingParam = pricingParam;
}
public String getAssociationType() {
return associationType;
}
public void setAssociationType(String associationType) {
this.associationType = associationType;
}
public int getAssetId() {
return assetId;
}
public void setAssetId(int assetId) {
this.assetId = assetId;
}
public int getClientId() {
return clientId;
}
public void setClientId(int clientId) {
this.clientId = clientId;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public String getCreatedTime() {
return createdTime;
}
public void setCreatedTime(String createdTime) {
this.createdTime = createdTime;
}
public String getLastUpdatedTime() {
return lastUpdatedTime;
}
public void setLastUpdatedTime(String lastUpdatedTime) {
this.lastUpdatedTime = lastUpdatedTime;
}
}

@ -108,6 +108,12 @@ public class Application {
value = "if the app is favoured by the user")
private boolean isFavourite;
@ApiModelProperty(name = "isExternalAppStoreApp",
value = "Is the app coming from an external application store",
required = true,
example = "true or false")
private boolean isExternalAppStoreApp;
public String getPackageName() {
return packageName;
}
@ -194,4 +200,12 @@ public class Application {
public void setFavourite(boolean favourite) {
isFavourite = favourite;
}
public boolean isExternalAppStoreApp() {
return isExternalAppStoreApp;
}
public void setExternalAppStoreApp(boolean externalAppStoreApp) {
isExternalAppStoreApp = externalAppStoreApp;
}
}

@ -24,6 +24,7 @@ import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import java.io.IOException;
import java.util.List;
public interface VPPApplicationManager {
@ -40,4 +41,7 @@ public interface VPPApplicationManager {
VppAssetDTO getAssetByAppId(String appId) throws ApplicationManagementException;
ProxyResponse callVPPBackend(String url, String payload, String accessToken, String method) throws IOException;
boolean addAssociation(VppAssetDTO asset, List<VppUserDTO> vppUsers) throws
ApplicationManagementException;
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2018 - 2023, 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 io.entgra.device.mgt.core.application.mgt.common.wrapper;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneAssetDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneUserDTO;
import java.util.ArrayList;
import java.util.List;
public class VppAssociateRequestWrapper {
List<VppItuneAssetDTO> assets;
List<String> clientUserIds;
public List<VppItuneAssetDTO> getAssets() {
return assets;
}
public void setAssets(List<VppItuneAssetDTO> assets) {
this.assets = assets;
}
public List<String> getClientUserIds() {
return clientUserIds;
}
public void setClientUserIds(List<String> clientUserIds) {
this.clientUserIds = clientUserIds;
}
}

@ -19,7 +19,13 @@
package io.entgra.device.mgt.core.application.mgt.core.impl;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.dao.VppApplicationDAO;
import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException;
import io.entgra.device.mgt.core.application.mgt.core.exception.UnexpectedServerErrorException;
import io.entgra.device.mgt.core.application.mgt.core.util.VppHttpUtil;
import io.entgra.device.mgt.core.device.mgt.extensions.logger.spi.EntgraLogger;
import io.entgra.device.mgt.core.notification.logger.AppInstallLogContext;
import io.entgra.device.mgt.core.notification.logger.impl.EntgraAppInstallLoggerImpl;
@ -118,12 +124,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
private static final EntgraLogger log = new EntgraAppInstallLoggerImpl(SubscriptionManagerImpl.class);
private SubscriptionDAO subscriptionDAO;
private ApplicationDAO applicationDAO;
private VppApplicationDAO vppApplicationDAO;
private LifecycleStateManager lifecycleStateManager;
public SubscriptionManagerImpl() {
this.lifecycleStateManager = DataHolder.getInstance().getLifecycleStateManager();
this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO();
this.applicationDAO = ApplicationManagementDAOFactory.getApplicationDAO();
this.vppApplicationDAO = ApplicationManagementDAOFactory.getVppApplicationDAO();
}
@Override
@ -148,6 +156,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
ApplicationDTO applicationDTO = getApplicationDTO(applicationUUID);
ApplicationSubscriptionInfo applicationSubscriptionInfo = getAppSubscriptionInfo(applicationDTO, subType,
params);
performExternalStoreSubscription(applicationDTO, applicationSubscriptionInfo);
ApplicationInstallResponse applicationInstallResponse = performActionOnDevices(
applicationSubscriptionInfo.getAppSupportingDeviceTypeName(), applicationSubscriptionInfo.getDevices(),
applicationDTO, subType, applicationSubscriptionInfo.getSubscribers(), action, properties, isOperationReExecutingDisabled);
@ -156,6 +165,50 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
return applicationInstallResponse;
}
private void performExternalStoreSubscription(ApplicationDTO applicationDTO,
ApplicationSubscriptionInfo
applicationSubscriptionInfo) throws ApplicationManagementException {
try {
// Only for iOS devices
if (DeviceTypes.IOS.toString().equalsIgnoreCase(APIUtil.getDeviceTypeData(applicationDTO
.getDeviceTypeId()).getName())) {
// TODO: replace getAssetByAppId with the correct one in DAO
// Check if the app trying to subscribe is a VPP asset.
VppAssetDTO storedAsset = vppApplicationDAO.getAssetByAppId(applicationDTO.getId());
if (storedAsset != null) { // This is a VPP asset
List<VppUserDTO> users = new ArrayList<>();
List<Device> devices = applicationSubscriptionInfo.getDevices();// get
// subscribed device list, so that we can extract the users of those devices.
for (Device device : devices) {
VppUserDTO user = vppApplicationDAO.getUserByDMUsername(device.getEnrolmentInfo()
.getOwner(), PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantId(true));
users.add(user);
}
VPPApplicationManager vppManager = APIUtil.getVPPManager();
vppManager.addAssociation(storedAsset, users);
}
}
} catch (BadRequestException e) {
String msg = "Device Type not found";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (UnexpectedServerErrorException e) {
String msg = "Unexpected error while getting device type";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementDAOException e) {
String msg = "Error while getting the device user";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
} catch (ApplicationManagementException e) {
String msg = "Error while associating user";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
}
@Override
public void createScheduledSubscription(ScheduledSubscriptionDTO subscriptionDTO)
throws SubscriptionManagementException {

@ -24,13 +24,15 @@ import com.google.gson.JsonParser;
import io.entgra.device.mgt.core.application.mgt.common.dto.ItuneAppDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssociationDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneAssetDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.exception.DBConnectionException;
import io.entgra.device.mgt.core.application.mgt.common.exception.TransactionManagementException;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserRequestWrapper;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import io.entgra.device.mgt.core.application.mgt.common.exception.DBConnectionException;
import io.entgra.device.mgt.core.application.mgt.common.exception.TransactionManagementException;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppAssociateRequestWrapper;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneAssetResponseWrapper;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserRequestWrapper;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserResponseWrapper;
@ -52,6 +54,8 @@ import org.apache.http.HttpStatus;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class VppApplicationManagerImpl implements VPPApplicationManager {
private static final String APP_API = "https://vpp.itunes.apple.com/mdm/v2";
@ -59,6 +63,7 @@ public class VppApplicationManagerImpl implements VPPApplicationManager {
private static final String USER_CREATE = APP_API + "/users/create";
private static final String USER_UPDATE = APP_API + "/users/update";
private static final String USER_GET = APP_API + "/users";
private static final String ASSIGNMENTS_POST = APP_API + "/assets/associate";
private static final String TOKEN = "";
private static final String LOOKUP_API = "https://uclient-api.itunes.apple" +
".com/WebObjects/MZStorePlatform.woa/wa/lookup?version=2&id=";
@ -267,6 +272,8 @@ public class VppApplicationManagerImpl implements VPPApplicationManager {
for (VppAssetDTO vppAssetDTO : vppItuneAssetResponse.getAssets()) {
ItuneAppDTO ituneAppDTO = lookupAsset(vppAssetDTO.getAdamId());
ApplicationManagementUtil.persistApp(ituneAppDTO);
}
// TODO: Store/update vppItuneAssetResponse.getAssets() in the DB
@ -366,4 +373,50 @@ public class VppApplicationManagerImpl implements VPPApplicationManager {
return VppHttpUtil.execute(url, payload, accessToken, method);
}
public boolean addAssociation(VppAssetDTO asset, List<VppUserDTO> vppUsers) throws
ApplicationManagementException {
List<VppAssociationDTO> associations = new ArrayList<>(); // To save to UEM DBs
List<String> clientUserIds = new ArrayList<>(); // Need this to send to vpp backend.
if (asset != null) {
for (VppUserDTO vppUserDTO : vppUsers) {
VppAssociationDTO associationDTO = VppHttpUtil.getAssociation(vppUserDTO, asset);
associations.add(associationDTO);
clientUserIds.add(vppUserDTO.getClientUserId());
}
if (associations.size() > 0) {
//TODO: Add or Update associations
try {
// Create the VPP backend payload
List<VppItuneAssetDTO> assets = new ArrayList<>();
VppItuneAssetDTO assetDTO = new VppItuneAssetDTO();
assetDTO.setAdamId(asset.getAdamId());
assetDTO.setPricingParam(asset.getPricingParam());
assets.add(assetDTO);
VppAssociateRequestWrapper vppAssociate = new VppAssociateRequestWrapper();
vppAssociate.setAssets(assets);
vppAssociate.setClientUserIds(clientUserIds);
Gson gson = new Gson();
String payload = gson.toJson(vppAssociate);
ProxyResponse proxyResponse = callVPPBackend(ASSIGNMENTS_POST, payload, TOKEN,
Constants.VPP.POST);
return true;
} catch (IOException e) {
String msg = "Error while adding associations";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
}
}
return false;
}
}

@ -17,26 +17,25 @@
*/
package io.entgra.device.mgt.core.application.mgt.core.internal;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.impl.AppmDataHandlerImpl;
import io.entgra.device.mgt.core.application.mgt.core.impl.VppApplicationManagerImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import io.entgra.device.mgt.core.application.mgt.common.config.LifecycleState;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationStorageManager;
import io.entgra.device.mgt.core.application.mgt.common.services.AppmDataHandler;
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.core.dao.common.ApplicationManagementDAOFactory;
import io.entgra.device.mgt.core.application.mgt.core.impl.AppmDataHandlerImpl;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.application.mgt.core.task.ScheduledAppSubscriptionTaskManager;
import io.entgra.device.mgt.core.application.mgt.core.util.ApplicationManagementUtil;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.ndatasource.core.DataSourceService;
import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.core.service.RealmService;
@ -118,9 +117,9 @@ public class ApplicationManagementServiceComponent {
DataHolder.getInstance().setConfigManager(configManager);
bundleContext.registerService(AppmDataHandler.class.getName(), configManager, null);
// TODO: Get the new instance from extension like others
VppApplicationManagerImpl vppApplicationManager = new VppApplicationManagerImpl();
VPPApplicationManager vppApplicationManager = ApplicationManagementUtil
.getVPPManagerInstance();
DataHolder.getInstance().setVppApplicationManager(vppApplicationManager);
bundleContext.registerService(VPPApplicationManager.class.getName(), vppApplicationManager, null);

@ -71,6 +71,7 @@ public class APIUtil {
private static volatile SubscriptionManager subscriptionManager;
private static volatile ReviewManager reviewManager;
private static volatile AppmDataHandler appmDataHandler;
private static volatile VPPApplicationManager vppApplicationManager;
public static SPApplicationManager getSPApplicationManager() {
if (SPApplicationManager == null) {
@ -200,6 +201,29 @@ public class APIUtil {
return reviewManager;
}
public static VPPApplicationManager getVPPManager() {
try {
if (vppApplicationManager == null) {
synchronized (APIUtil.class) {
if (vppApplicationManager == null) {
vppApplicationManager = ApplicationManagementUtil.getVPPManagerInstance();
if (vppApplicationManager == null) {
String msg = "Vpp Manager service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
}
}
}
} catch (Exception e) {
String msg = "Error occurred while getting the vpp manager";
log.error(msg);
throw new IllegalStateException(msg);
}
return vppApplicationManager;
}
/**
* To get the DataHandler from the osgi context.
* @return AppmDataHandler instance in the current osgi context.
@ -424,9 +448,13 @@ public class APIUtil {
}
List<ApplicationRelease> applicationReleases = new ArrayList<>();
if (ApplicationType.PUBLIC.toString().equals(applicationDTO.getType()) && application.getCategories()
.contains("GooglePlaySyncedApp")) {
.contains(Constants.GOOGLE_PLAY_SYNCED_APP)) {
application.setAndroidEnterpriseApp(true);
}
if (ApplicationType.PUBLIC.toString().equals(applicationDTO.getType()) && application.getCategories()
.contains(Constants.ApplicationProperties.APPLE_STORE_SYNCED_APP_CATEGORY)) {
application.setExternalAppStoreApp(true);
}
for (ApplicationReleaseDTO applicationReleaseDTO : applicationDTO.getApplicationReleaseDTOs()) {
applicationReleases.add(releaseDtoToRelease(applicationReleaseDTO));
}

@ -32,6 +32,7 @@ import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationStor
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.ApplicationUpdateWrapper;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.ApplicationWrapper;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.CustomAppReleaseWrapper;
@ -44,6 +45,7 @@ import io.entgra.device.mgt.core.application.mgt.common.wrapper.WebAppWrapper;
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.core.config.Extension;
import io.entgra.device.mgt.core.application.mgt.core.exception.BadRequestException;
import io.entgra.device.mgt.core.application.mgt.core.impl.VppApplicationManagerImpl;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.device.mgt.common.Base64File;
import io.entgra.device.mgt.core.device.mgt.common.DeviceManagementConstants;
@ -202,6 +204,11 @@ public class ApplicationManagementUtil {
return getInstance(extension, LifecycleStateManager.class);
}
public static VPPApplicationManager getVPPManagerInstance() {
// TODO: implement as an extension
return new VppApplicationManagerImpl();
}
/**
* This is useful to delete application artifacts if any error occurred while creating release/application
* after uploading the artifacts

@ -73,6 +73,7 @@ public class Constants {
public static final String GOOGLE_PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=";
public static final String APPLE_STORE_URL = "https://itunes.apple.com/country/app/app-name/id";
public static final String GOOGLE_PLAY_SYNCED_APP = "GooglePlaySyncedApp";
// Subscription task related constants
public static final String SUBSCRIBERS = "SUBSCRIBERS";
@ -207,5 +208,7 @@ public class Constants {
public static final String DISPLAY = "display";
public static final String GENRE_NAMES = "genreNames";
public static final String PRICE_ZERO = "0.0";
public static final String ASSOCIATION_DEVICE = "ASSOCIATION_DEVICE";
public static final String ASSOCIATION_USER = "ASSOCIATION_USER";
}
}

@ -20,6 +20,9 @@ package io.entgra.device.mgt.core.application.mgt.core.util;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssetDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppAssociationDTO;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -39,6 +42,7 @@ import org.apache.http.impl.client.HttpClients;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
@ -282,4 +286,20 @@ public class VppHttpUtil {
return HttpClients.custom().setMaxConnTotal(1).setMaxConnPerRoute(1).build();
}
public static VppAssociationDTO getAssociation(VppUserDTO user, VppAssetDTO asset) {
VppAssociationDTO associationDTO = new VppAssociationDTO();
associationDTO.setAdamId(asset.getAdamId());
associationDTO.setClientUserId(user.getClientUserId());
associationDTO.setPricingParam(asset.getPricingParam());
associationDTO.setAssociationType(Constants.ApplicationProperties.ASSOCIATION_USER);
associationDTO.setAssetId(asset.getId());
associationDTO.setClientId(user.getId());
associationDTO.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantId(true));
associationDTO.setCreatedTime(String.valueOf(System.currentTimeMillis()));
associationDTO.setLastUpdatedTime(String.valueOf(System.currentTimeMillis()));
return associationDTO;
}
}

Loading…
Cancel
Save